Tony Asleson
2014-08-11 22:47:41 UTC
Signed-off-by: Tony Asleson <***@redhat.com>
---
c_binding/lsm_mgmt.cpp | 121 +++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 116 insertions(+), 5 deletions(-)
diff --git a/c_binding/lsm_mgmt.cpp b/c_binding/lsm_mgmt.cpp
index 5805cf9..3fed4f9 100644
--- a/c_binding/lsm_mgmt.cpp
+++ b/c_binding/lsm_mgmt.cpp
@@ -25,6 +25,7 @@
#include <string.h>
#include <dirent.h>
#include <libxml/uri.h>
+#include <regex.h>
#include "lsm_datatypes.hpp"
#include "lsm_convert.hpp"
@@ -76,6 +77,105 @@ static int check_search_key(const char *search_key,
return 0;
}
+static int reg_ex_match(const char *pattern, const char *str)
+{
+ regex_t start_state;
+ int status = 0;
+ int rc = regcomp(&start_state, pattern, REG_EXTENDED);
+
+ if (rc) {
+ // Development only when changing regular expression
+ fprintf(stderr, "%s: bad pattern: '%s' %d\n", str, pattern, rc);
+ return -1;
+ }
+
+ status = regexec(&start_state, str, 0, NULL, 0);
+ regfree(&start_state);
+
+ return status;
+}
+
+/**
+ * Validates an iSCSI IQN
+ * @param iqn iSCSI iqn to check
+ * @return 0 on success, else error
+ */
+static int iqn_validate(const char *iqn)
+{
+ // Pattern derived from http://tools.ietf.org/html/rfc3720#page-32
+ const char *pattern =
+ "^iqn" // iqn
+ "\\."
+ "[0-9]{4}-0[1-9]|1[0-2]" // Data code yyyy-mm
+ "\\."
+ "[a-zA-Z]{2,}" // TLD
+ "\\."
+ "[a-zA-Z0-9]([a-zA-Z0-9-]{0,61})?" // Domain
+ "(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61})?)*" // Optional sub domain(s)
+ "(:.+)?$"; // Optional, user defined
+
+ if( iqn && strlen(iqn) ) {
+ return reg_ex_match(pattern, iqn);
+ } else {
+ return 1;
+ }
+}
+
+/**
+ * Given a WWPN validate it and then convert to internal representation.
+ * @param wwpn World wide port name to validate
+ * @return NULL if not patch, else string with common lsm format
+ */
+static char *wwpn_validate(const char *wwpn)
+{
+ size_t i = 0;
+ size_t out = 0;
+ char *rc = NULL;
+ const char *pattern = "^(0x|0X)?([0-9A-Fa-f]{2})"
+ "(([\\.\\:\\-])?[0-9A-Fa-f]{2}){7}$";
+ int bad = reg_ex_match(pattern, wwpn);
+
+ if( !bad ) {
+ rc = (char*)calloc(24,1);
+ size_t len = strlen(wwpn);
+
+ if (wwpn[1] == 'x' || wwpn[1] == 'X') {
+ i = 2;
+ }
+
+ for( ; i < len; ++i ) {
+ if( wwpn[i] != ':' && wwpn[i] != '-' && wwpn[i] != '.') {
+ rc[out++] = tolower(wwpn[i]);
+ } else {
+ rc[out++] = ':';
+ }
+ }
+ }
+ return rc;
+}
+
+static int verify_initiator_id(const char *id, lsm_access_group_init_type t,
+ Value &initiator)
+{
+ initiator = Value(id);
+
+ if( t == LSM_ACCESS_GROUP_INIT_TYPE_WWPN ) {
+ char *wwpn = wwpn_validate(id);
+ if( wwpn ) {
+ initiator = Value(wwpn);
+ free(wwpn);
+ wwpn = NULL;
+ } else {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+ } else if( t == LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN ) {
+ if( iqn_validate(id) ) {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+ }
+ return LSM_ERR_OK;
+}
+
/**
* Strings are non null with a len >= 1
*/
@@ -1177,7 +1277,7 @@ int lsm_volume_replicate(lsm_connect *c, lsm_pool *pool,
{
CONN_SETUP(c);
- if( pool && !LSM_IS_POOL(pool) || !LSM_IS_VOL(volumeSrc) ) {
+ if( (pool && !LSM_IS_POOL(pool)) || !LSM_IS_VOL(volumeSrc) ) {
return LSM_ERR_INVALID_ARGUMENT;
}
@@ -1319,8 +1419,7 @@ int lsm_iscsi_chap_auth(lsm_connect *c, const char *init_id,
{
CONN_SETUP(c);
- if( NULL == init_id || strlen(init_id) == 0 ||
- LSM_FLAG_UNUSED_CHECK(flags)) {
+ if( iqn_validate(init_id) || LSM_FLAG_UNUSED_CHECK(flags)) {
return LSM_ERR_INVALID_ARGUMENT;
}
@@ -1411,9 +1510,15 @@ int lsm_access_group_create(lsm_connect *c, const char *name,
return LSM_ERR_INVALID_ARGUMENT;
}
+ Value id;
+
+ if( LSM_ERR_OK != verify_initiator_id(init_id, init_type, id) ) {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+
std::map<std::string, Value> p;
p["name"] = Value(name);
- p["init_id"] = Value(init_id);
+ p["init_id"] = id;
p["init_type"] = Value((int32_t)init_type);
p["system"] = system_to_value(system);
p["flags"] = Value(flags);
@@ -1466,9 +1571,15 @@ int lsm_access_group_initiator_add(lsm_connect *c,
return LSM_ERR_INVALID_ARGUMENT;
}
+ Value id;
+
+ if( LSM_ERR_OK != verify_initiator_id(init_id, init_type, id) ) {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+
std::map<std::string, Value> p;
p["access_group"] = access_group_to_value(access_group);
- p["init_id"] = init_id;
+ p["init_id"] = id;
p["init_type"] = Value((int32_t)init_type);
p["flags"] = Value(flags);
---
c_binding/lsm_mgmt.cpp | 121 +++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 116 insertions(+), 5 deletions(-)
diff --git a/c_binding/lsm_mgmt.cpp b/c_binding/lsm_mgmt.cpp
index 5805cf9..3fed4f9 100644
--- a/c_binding/lsm_mgmt.cpp
+++ b/c_binding/lsm_mgmt.cpp
@@ -25,6 +25,7 @@
#include <string.h>
#include <dirent.h>
#include <libxml/uri.h>
+#include <regex.h>
#include "lsm_datatypes.hpp"
#include "lsm_convert.hpp"
@@ -76,6 +77,105 @@ static int check_search_key(const char *search_key,
return 0;
}
+static int reg_ex_match(const char *pattern, const char *str)
+{
+ regex_t start_state;
+ int status = 0;
+ int rc = regcomp(&start_state, pattern, REG_EXTENDED);
+
+ if (rc) {
+ // Development only when changing regular expression
+ fprintf(stderr, "%s: bad pattern: '%s' %d\n", str, pattern, rc);
+ return -1;
+ }
+
+ status = regexec(&start_state, str, 0, NULL, 0);
+ regfree(&start_state);
+
+ return status;
+}
+
+/**
+ * Validates an iSCSI IQN
+ * @param iqn iSCSI iqn to check
+ * @return 0 on success, else error
+ */
+static int iqn_validate(const char *iqn)
+{
+ // Pattern derived from http://tools.ietf.org/html/rfc3720#page-32
+ const char *pattern =
+ "^iqn" // iqn
+ "\\."
+ "[0-9]{4}-0[1-9]|1[0-2]" // Data code yyyy-mm
+ "\\."
+ "[a-zA-Z]{2,}" // TLD
+ "\\."
+ "[a-zA-Z0-9]([a-zA-Z0-9-]{0,61})?" // Domain
+ "(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61})?)*" // Optional sub domain(s)
+ "(:.+)?$"; // Optional, user defined
+
+ if( iqn && strlen(iqn) ) {
+ return reg_ex_match(pattern, iqn);
+ } else {
+ return 1;
+ }
+}
+
+/**
+ * Given a WWPN validate it and then convert to internal representation.
+ * @param wwpn World wide port name to validate
+ * @return NULL if not patch, else string with common lsm format
+ */
+static char *wwpn_validate(const char *wwpn)
+{
+ size_t i = 0;
+ size_t out = 0;
+ char *rc = NULL;
+ const char *pattern = "^(0x|0X)?([0-9A-Fa-f]{2})"
+ "(([\\.\\:\\-])?[0-9A-Fa-f]{2}){7}$";
+ int bad = reg_ex_match(pattern, wwpn);
+
+ if( !bad ) {
+ rc = (char*)calloc(24,1);
+ size_t len = strlen(wwpn);
+
+ if (wwpn[1] == 'x' || wwpn[1] == 'X') {
+ i = 2;
+ }
+
+ for( ; i < len; ++i ) {
+ if( wwpn[i] != ':' && wwpn[i] != '-' && wwpn[i] != '.') {
+ rc[out++] = tolower(wwpn[i]);
+ } else {
+ rc[out++] = ':';
+ }
+ }
+ }
+ return rc;
+}
+
+static int verify_initiator_id(const char *id, lsm_access_group_init_type t,
+ Value &initiator)
+{
+ initiator = Value(id);
+
+ if( t == LSM_ACCESS_GROUP_INIT_TYPE_WWPN ) {
+ char *wwpn = wwpn_validate(id);
+ if( wwpn ) {
+ initiator = Value(wwpn);
+ free(wwpn);
+ wwpn = NULL;
+ } else {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+ } else if( t == LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN ) {
+ if( iqn_validate(id) ) {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+ }
+ return LSM_ERR_OK;
+}
+
/**
* Strings are non null with a len >= 1
*/
@@ -1177,7 +1277,7 @@ int lsm_volume_replicate(lsm_connect *c, lsm_pool *pool,
{
CONN_SETUP(c);
- if( pool && !LSM_IS_POOL(pool) || !LSM_IS_VOL(volumeSrc) ) {
+ if( (pool && !LSM_IS_POOL(pool)) || !LSM_IS_VOL(volumeSrc) ) {
return LSM_ERR_INVALID_ARGUMENT;
}
@@ -1319,8 +1419,7 @@ int lsm_iscsi_chap_auth(lsm_connect *c, const char *init_id,
{
CONN_SETUP(c);
- if( NULL == init_id || strlen(init_id) == 0 ||
- LSM_FLAG_UNUSED_CHECK(flags)) {
+ if( iqn_validate(init_id) || LSM_FLAG_UNUSED_CHECK(flags)) {
return LSM_ERR_INVALID_ARGUMENT;
}
@@ -1411,9 +1510,15 @@ int lsm_access_group_create(lsm_connect *c, const char *name,
return LSM_ERR_INVALID_ARGUMENT;
}
+ Value id;
+
+ if( LSM_ERR_OK != verify_initiator_id(init_id, init_type, id) ) {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+
std::map<std::string, Value> p;
p["name"] = Value(name);
- p["init_id"] = Value(init_id);
+ p["init_id"] = id;
p["init_type"] = Value((int32_t)init_type);
p["system"] = system_to_value(system);
p["flags"] = Value(flags);
@@ -1466,9 +1571,15 @@ int lsm_access_group_initiator_add(lsm_connect *c,
return LSM_ERR_INVALID_ARGUMENT;
}
+ Value id;
+
+ if( LSM_ERR_OK != verify_initiator_id(init_id, init_type, id) ) {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+
std::map<std::string, Value> p;
p["access_group"] = access_group_to_value(access_group);
- p["init_id"] = init_id;
+ p["init_id"] = id;
p["init_type"] = Value((int32_t)init_type);
p["flags"] = Value(flags);
--
1.8.2.1
1.8.2.1