diff --git a/common/fko_util.c b/common/fko_util.c index 7095c54c..586abce1 100644 --- a/common/fko_util.c +++ b/common/fko_util.c @@ -958,4 +958,99 @@ dump_ctx_to_buffer(fko_ctx_t ctx, char *dump_buf, size_t dump_buf_len) return (err); } +/** + * @brief Grab the sin address from the sockaddr structure. + * + * This function returns the sin address as a sockaddr_in or sockaddr_in6 + * structure according to the family set (ipv4 or ipv6) in the sockaddr + * structure. + * + * @param sa sockaddr strcuture + * + * @return the sin addr if the sa family is AF_INET or the sin6_addr otherwise. + */ +static void * +get_in_addr(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) + { + return &(((struct sockaddr_in*)sa)->sin_addr); + } + + else + { + return &(((struct sockaddr_in6*)sa)->sin6_addr); + } +} + +/** + * @brief Resolve a domain name as an IP address. + * + * @param dns_str Name of the host to resolve. + * @param hints Hints to reduce the number of result from getaddrinfo() + * @param ip_str String where to store the resolve ip address + * @param ip_bufsize Number of bytes available in the ip_str buffer + * @param opts Client command line options + * + * @return 0 if successful, 1 if an error occured. + */ +int +ipv4_resolve(const char *dns_str, char *ip_str) +{ + int error; /* Function error return code */ + size_t ip_bufsize = MAX_IPV4_STR_LEN; + struct addrinfo hints; + struct addrinfo *result; /* Result of getaddrinfo() */ + struct addrinfo *rp; /* Element of the linked list returned by getaddrinfo() */ +#if WIN32 && WINVER <= 0x0600 + struct sockaddr_in *in; + char *win_ip; +#else + struct sockaddr_in *sai_remote; /* Remote host information as a sockaddr_in structure */ +#endif + + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + /* Try to resolve the host name */ + error = getaddrinfo(dns_str, NULL, &hints, &result); + if (error != 0) + fprintf(stderr, "resolve_dst_addr() : %s\n", gai_strerror(error)); + + else + { + error = 1; + + /* Go through the linked list of addrinfo structures */ + for (rp = result; rp != NULL; rp = rp->ai_next) + { + memset(ip_str, 0, ip_bufsize); + +#if WIN32 && WINVER <= 0x0600 + /* On older Windows systems (anything before Vista?), + * we use inet_ntoa for now. + */ + in = (struct sockaddr_in*)(rp->ai_addr); + win_ip = inet_ntoa(in->sin_addr); + + if (win_ip != NULL && (strlcpy(ip_str, win_ip, ip_bufsize) > 0)) +#else + sai_remote = (struct sockaddr_in *)get_in_addr((struct sockaddr *)(rp->ai_addr)); + if (inet_ntop(rp->ai_family, sai_remote, ip_str, ip_bufsize) != NULL) +#endif + { + error = 0; + break; + } + } + + /* Free our result from getaddrinfo() */ + freeaddrinfo(result); + } + + return error; +} + + /***EOF***/ diff --git a/common/fko_util.h b/common/fko_util.h index bbece991..da45e786 100644 --- a/common/fko_util.h +++ b/common/fko_util.h @@ -35,7 +35,6 @@ #define MAX_CMDLINE_ARGS 30 /*!< should be way more than enough */ #define MAX_ARGS_LINE_LEN 1024 - /* Function prototypes */ int is_valid_encoded_msg_len(const int len); @@ -65,6 +64,8 @@ void chop_spaces(char *str); int strtoargv(const char * const args_str, char **argv_new, int *argc_new); void free_argv(char **argv_new, int *argc_new); +int ipv4_resolve(const char *dns_str, char *ip_str); + #if !HAVE_STRLCAT size_t strlcat(char *dst, const char *src, size_t siz); #endif @@ -79,6 +80,17 @@ char * strndup( const char * s, size_t len ); int dump_ctx_to_buffer(fko_ctx_t ctx, char *dump_buf, size_t dump_buf_len); +#include +#ifdef WIN32 + #include + #include +#else + #if HAVE_SYS_SOCKET_H + #include + #endif + #include +#endif + #endif /* FKO_UTIL_H */ /***EOF***/ diff --git a/lib/fko_message.c b/lib/fko_message.c index c1273117..de3d1b9e 100644 --- a/lib/fko_message.c +++ b/lib/fko_message.c @@ -311,9 +311,10 @@ validate_nat_access_msg(const char *msg) return(FKO_ERROR_INVALID_DATA_MESSAGE_NAT_MISSING); /* Should always have a valid allow IP regardless of message type - */ + * if((res = have_allow_ip(msg)) != FKO_SUCCESS) return(FKO_ERROR_INVALID_SPA_NAT_ACCESS_MSG); + */ /* Position ourselves beyond the allow IP and make sure we have * a single port value diff --git a/server/fw_util_firewalld.c b/server/fw_util_firewalld.c index f8d5ae1b..0f13ff8f 100644 --- a/server/fw_util_firewalld.c +++ b/server/fw_util_firewalld.c @@ -1319,6 +1319,7 @@ process_spa_request(const fko_srv_options_t * const opts, const acc_stanza_t * const acc, spa_data_t * const spadat) { char nat_ip[MAX_IPV4_STR_LEN] = {0}; + char nat_dst[64] = {0}; //not finding a MAX_HOSTNAME_LEN #define unsigned int nat_port = 0; unsigned int fst_proto; unsigned int fst_port; @@ -1381,12 +1382,23 @@ process_spa_request(const fko_srv_options_t * const opts, ndx = strchr(spadat->nat_access, ','); if(ndx != NULL) { - strlcpy(nat_ip, spadat->nat_access, (ndx-spadat->nat_access)+1); - if (! is_valid_ipv4_addr(nat_ip)) + strlcpy(nat_dst, spadat->nat_access, (ndx-spadat->nat_access)+1); + if (! is_valid_ipv4_addr(nat_dst)) { - log_msg(LOG_INFO, "Invalid NAT IP in SPA message"); - free_acc_port_list(port_list); - return res; + if (ipv4_resolve(nat_dst, nat_ip) == 0) + { + log_msg(LOG_INFO, "Resolved NAT IP in SPA message"); + } + else + { + log_msg(LOG_INFO, "Invalid NAT IP in SPA message"); + free_acc_port_list(port_list); + return res; + } + } + else + { + strlcpy(nat_ip, nat_dst, MAX_IPV4_STR_LEN); } nat_port = strtol_wrapper(ndx+1, 0, MAX_PORT, diff --git a/server/fw_util_iptables.c b/server/fw_util_iptables.c index ef9dabf5..d54101ec 100644 --- a/server/fw_util_iptables.c +++ b/server/fw_util_iptables.c @@ -1305,6 +1305,8 @@ process_spa_request(const fko_srv_options_t * const opts, const acc_stanza_t * const acc, spa_data_t * const spadat) { char nat_ip[MAX_IPV4_STR_LEN] = {0}; + char nat_dst[64] = {0}; //not finding a MAX_HOSTNAME_LEN #define + unsigned int nat_port = 0; unsigned int fst_proto; unsigned int fst_port; @@ -1367,12 +1369,23 @@ process_spa_request(const fko_srv_options_t * const opts, ndx = strchr(spadat->nat_access, ','); if(ndx != NULL) { - strlcpy(nat_ip, spadat->nat_access, (ndx-spadat->nat_access)+1); - if (! is_valid_ipv4_addr(nat_ip)) + strlcpy(nat_dst, spadat->nat_access, (ndx-spadat->nat_access)+1); + if (! is_valid_ipv4_addr(nat_dst)) { - log_msg(LOG_INFO, "Invalid NAT IP in SPA message"); - free_acc_port_list(port_list); - return res; + if (ipv4_resolve(nat_dst, nat_ip) == 0) + { + log_msg(LOG_INFO, "Resolved NAT IP in SPA message"); + } + else + { + log_msg(LOG_INFO, "Invalid NAT IP in SPA message"); + free_acc_port_list(port_list); + return res; + } + } + else + { + strlcpy(nat_ip, nat_dst, MAX_IPV4_STR_LEN); } nat_port = strtol_wrapper(ndx+1, 0, MAX_PORT,