From b708b18b833d1f2ba4da394884bc762a821ff56b Mon Sep 17 00:00:00 2001 From: Kaushal M Date: Tue, 23 Aug 2011 12:23:53 +0530 Subject: cli, protocol/server : improve validation for the option auth.(allow/reject) cli now checks validity of address list given for 'volume set auth.*' Server xlator checks addresses supplied to auth.(allow/reject) option including wildcards for correctness in case volfile is manually edited. Original patch done by shylesh@gluster.com Original patch is at http://patches.gluster.com/patch/7566/ Change-Id: Icf52d6eeef64d6632b15aa90a379fadacdf74fef BUG: 764197 Signed-off-by: Kaushal M Reviewed-on: http://review.gluster.com/306 Tested-by: Gluster Build System Reviewed-by: Jeff Darcy Reviewed-by: Vijay Bellur --- cli/src/cli-cmd-parser.c | 50 +++++++++++- libglusterfs/src/common-utils.c | 149 +++++++++++++++++++++++++++++------ libglusterfs/src/common-utils.h | 3 + xlators/protocol/server/src/server.c | 43 +++++++++- 4 files changed, 216 insertions(+), 29 deletions(-) diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index ef69235d673..b169b77c68d 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -36,7 +36,6 @@ #include "protocol-common.h" #include "cli1-xdr.h" - static const char * id_sel (void *wcon) { @@ -635,6 +634,43 @@ out: return ret; } +int32_t +cli_cmd_valid_ip_list (char *iplist) +{ + int ret = 0; + char *duplist = NULL; + char *addr = NULL; + char *saveptr = NULL; + + GF_ASSERT (iplist); + duplist = gf_strdup (iplist); + + if (!duplist) { + ret = -1; + goto out; + } + + addr = strtok_r (duplist, ",", &saveptr); + if (!addr) { + ret = -1; + goto out; + } + while (addr) { + if (!valid_internet_address (addr) && + !valid_wildcard_internet_address (addr)) { + cli_out ("Invalid ip or wildcard : %s", addr); + ret= -1; + goto out; + } + addr = strtok_r (NULL, ",", &saveptr); + } +out: + if (duplist) + GF_FREE (duplist); + gf_log ("cli", GF_LOG_INFO, "Returning %d", ret); + return ret; +} + int32_t cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options) { @@ -691,10 +727,18 @@ cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options) if ( !key || !value) { ret = -1; goto out; - } + } count++; - + if (!strncmp ("auth.allow", key, sizeof (key)) || + !strncmp ("auth.reject", key, sizeof (key))) { + ret = cli_cmd_valid_ip_list (value); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, + "invalid ips given"); + goto out; + } + } sprintf (str, "key%d", count); ret = dict_set_str (dict, str, key); if (ret) diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 42bfd035569..068bd846027 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -1529,30 +1529,36 @@ get_nth_word (const char *str, int n) } /* RFC 1123 & 952 */ + +/* The functions below validate given internet addresses and + * wildcard internet address for correctness. + * All return 1 on success and 0 on failure + */ + char valid_host_name (char *address, int length) { - int i = 0; - char ret = 1; + int i = 0; + char ret = 0; + int flag = 0; - if ((length > 75) || (length == 1)) { - ret = 0; + if ((length > 255) || (length == 1)) goto out; - } - if (!isalnum (address[length - 1])) { - ret = 0; + if (!isalnum (address[length - 1])) goto out; - } for (i = 0; i < length; i++) { if (!isalnum (address[i]) && (address[i] != '.') - && (address[i] != '-')) { - ret = 0; + && (address[i] != '-')) goto out; - } + + if (isalpha(address[i])) + flag = 1; } + if (flag) + ret = 1; out: return ret; } @@ -1563,7 +1569,7 @@ valid_ipv4_address (char *address, int length) int octets = 0; int value = 0; char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL; - char ret = 1; + char ret = 0; tmp = gf_strdup (address); prev = tmp; @@ -1572,16 +1578,14 @@ valid_ipv4_address (char *address, int length) while (prev != NULL) { octets++; value = strtol (prev, &endptr, 10); - if ((value > 255) || (value < 0) || (endptr != NULL)) { - ret = 0; + if ((value > 255) || (value < 0) || + (endptr != NULL && *endptr != '\0')) goto out; - } prev = strtok_r (NULL, ".", &ptr); } - if (octets != 4) { - ret = 0; - } + if (octets == 4) + ret = 1; out: GF_FREE (tmp); @@ -1594,7 +1598,7 @@ valid_ipv6_address (char *address, int length) int hex_numbers = 0; int value = 0; char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL; - char ret = 1; + char ret = 0; tmp = gf_strdup (address); prev = strtok_r (tmp, ":", &ptr); @@ -1603,16 +1607,13 @@ valid_ipv6_address (char *address, int length) hex_numbers++; value = strtol (prev, &endptr, 16); if ((value > 0xffff) || (value < 0) - || (endptr != NULL && *endptr != '\0')) { - ret = 0; + || (endptr != NULL && *endptr != '\0')) goto out; - } prev = strtok_r (NULL, ":", &ptr); } - if (hex_numbers > 8) { - ret = 0; - } + if (hex_numbers <= 8) + ret = 1; out: GF_FREE (tmp); @@ -1643,6 +1644,104 @@ out: return ret; } +char +valid_ipv4_wildcard_check (char *address) +{ + char ret = 0; + int octets = 0; + char *tmp = NULL; + char *prev = NULL; + char *endptr = NULL; + int value = 0; + int is_wildcard = 0; + + tmp = gf_strdup (address); + prev = strtok (tmp, "."); + + while (prev != NULL) { + octets++; + + if (!strcmp (prev, "*")) { + is_wildcard = 1; + } else { + value = strtol (prev, &endptr, 10); + + if ((value > 255) || (value < 0) || + (endptr != NULL && *endptr != '\0')) + goto out; + } + prev = strtok (NULL, "."); + } + + if (is_wildcard && (octets <= 4)) + ret = 1; + +out: + if (tmp) + GF_FREE (tmp); + return ret; + +} + +char +valid_ipv6_wildcard_check (char *address) +{ + char ret = 0; + int hex_numbers = 0; + int value = 0; + char *tmp = NULL; + char *prev = NULL; + char *endptr = NULL; + int is_wildcard = 0; + + tmp = gf_strdup (address); + prev = strtok (tmp, ":"); + + while (prev != NULL) { + hex_numbers++; + + if (!strcmp (prev, "*")) { + is_wildcard = 1; + } else { + value = strtol (prev, &endptr, 16); + + if ((value > 0xffff) || (value < 0) || + (endptr != NULL && *endptr != '\0')) + goto out; + } + prev = strtok (NULL, ":"); + } + + if (is_wildcard && (hex_numbers <= 8)) + ret = 1; +out: + if (tmp) + GF_FREE (tmp); + return ret; +} + +char +valid_wildcard_internet_address (char *address) +{ + char ret = 0; + + if (address == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, + "argument invalid"); + goto out; + } + + if (strlen (address) == 0) + goto out; + + if (valid_ipv4_wildcard_check (address) || + valid_ipv6_wildcard_check (address)) + ret = 1; + +out: + return ret; +} + /*Thread safe conversion function*/ char * uuid_utoa (uuid_t uuid) diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 4647c4a4d9c..63566fb53bc 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -445,6 +445,9 @@ char valid_host_name (char *address, int length); char valid_ipv4_address (char *address, int length); char valid_ipv6_address (char *address, int length); char valid_internet_address (char *address); +char valid_ipv4_wildcard_check (char *address); +char valid_ipv6_wildcard_check (char *address); +char valid_wildcard_internet_address (char *address); char *uuid_utoa (uuid_t uuid); char *uuid_utoa_r (uuid_t uuid, char *dst); diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c index 60bc517ddbe..b0697bb7b9d 100644 --- a/xlators/protocol/server/src/server.c +++ b/xlators/protocol/server/src/server.c @@ -469,6 +469,8 @@ validate_auth_options (xlator_t *this, dict_t *dict) xlator_list_t *trav = NULL; data_pair_t *pair = NULL; char *tail = NULL; + char *addr = NULL; + char *tmp_str = NULL; GF_VALIDATE_OR_GOTO ("server", this, out); GF_VALIDATE_OR_GOTO ("server", dict, out); @@ -492,9 +494,47 @@ validate_auth_options (xlator_t *this, dict_t *dict) if (*tail == '.') { error = 0; - break; + + /* when we are here, the key is checked for + * valid auth.allow. + * Now we verify the ip address + */ + if (!strcmp (pair->value->data, "*")) { + error = 0; + goto out; + } + + addr = strtok_r (pair->value->data, ",", + &tmp_str); + if (!addr) + addr = pair->value->data; + + while (addr) { + + if (valid_internet_address (addr) || + valid_wildcard_internet_address (addr)) + { + error = 0; + } else { + error = -1; + gf_log (this->name, GF_LOG_ERROR, + "internet address '%s'" + " does not conform to" + " standards.", addr); + goto out; + + } + if (tmp_str) + addr = strtok_r (NULL, ",", + &tmp_str); + else + addr = NULL; + } + } + } + if (-1 == error) { gf_log (this->name, GF_LOG_ERROR, "volume '%s' defined as subvolume, but no " @@ -504,6 +544,7 @@ validate_auth_options (xlator_t *this, dict_t *dict) } trav = trav->next; } + out: return error; } -- cgit