diff --git a/lib/fko_message.c b/lib/fko_message.c index fa6803b2..c2a86bb5 100644 --- a/lib/fko_message.c +++ b/lib/fko_message.c @@ -33,14 +33,6 @@ #include "fko_message.h" #include "fko.h" -#ifndef WIN32 - /* for inet_aton() IP validation - */ - #include - #include - #include -#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); } diff --git a/lib/fko_util.c b/lib/fko_util.c index 1385d7df..e098464d 100644 --- a/lib/fko_util.c +++ b/lib/fko_util.c @@ -33,6 +33,14 @@ #include #include +#ifndef WIN32 + /* for inet_aton() IP validation + */ + #include + #include + #include +#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 diff --git a/lib/fko_util.h b/lib/fko_util.h index 7e581e28..7d2de796 100644 --- a/lib/fko_util.h +++ b/lib/fko_util.h @@ -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); diff --git a/server/access.c b/server/access.c index 43b5863b..203d2d89 100644 --- a/server/access.c +++ b/server/access.c @@ -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); diff --git a/server/config_init.c b/server/config_init.c index 6c80947e..019584df 100644 --- a/server/config_init.c +++ b/server/config_init.c @@ -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) diff --git a/server/fw_util_iptables.c b/server/fw_util_iptables.c index 142dd281..559ca93c 100644 --- a/server/fw_util_iptables.c +++ b/server/fw_util_iptables.c @@ -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; } } diff --git a/server/incoming_spa.c b/server/incoming_spa.c index f80a76ea..08c39be0 100644 --- a/server/incoming_spa.c +++ b/server/incoming_spa.c @@ -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));