diff --git a/lib/libiscsiutil/libiscsiutil.h b/lib/libiscsiutil/libiscsiutil.h --- a/lib/libiscsiutil/libiscsiutil.h +++ b/lib/libiscsiutil/libiscsiutil.h @@ -154,6 +154,9 @@ void connection_init(struct connection *conn, const struct connection_ops *ops, bool use_proxy); +bool valid_iscsi_name(const char *name, + void (*warn_fn)(const char *, ...)); + void log_init(int level); void log_set_peer_name(const char *name); void log_set_peer_addr(const char *addr); diff --git a/lib/libiscsiutil/utils.c b/lib/libiscsiutil/utils.c --- a/lib/libiscsiutil/utils.c +++ b/lib/libiscsiutil/utils.c @@ -28,10 +28,13 @@ * SUCH DAMAGE. */ +#include #include #include "libiscsiutil.h" +#define MAX_NAME_LEN 223 + char * checked_strdup(const char *s) { @@ -42,3 +45,71 @@ log_err(1, "strdup"); return (c); } + +bool +valid_iscsi_name(const char *name, void (*warn_fn)(const char *, ...)) +{ + int i; + + if (strlen(name) >= MAX_NAME_LEN) { + warn_fn("overlong name for target \"%s\"; max length allowed " + "by iSCSI specification is %d characters", + name, MAX_NAME_LEN); + return (false); + } + + /* + * In the cases below, we don't return an error, just in case the admin + * was right, and we're wrong. + */ + if (strncasecmp(name, "iqn.", strlen("iqn.")) == 0) { + for (i = strlen("iqn."); name[i] != '\0'; i++) { + /* + * XXX: We should verify UTF-8 normalisation, as defined + * by 3.2.6.2: iSCSI Name Encoding. + */ + if (isalnum(name[i])) + continue; + if (name[i] == '-' || name[i] == '.' || name[i] == ':') + continue; + warn_fn("invalid character \"%c\" in target name " + "\"%s\"; allowed characters are letters, digits, " + "'-', '.', and ':'", name[i], name); + break; + } + /* + * XXX: Check more stuff: valid date and a valid reversed domain. + */ + } else if (strncasecmp(name, "eui.", strlen("eui.")) == 0) { + if (strlen(name) != strlen("eui.") + 16) + warn_fn("invalid target name \"%s\"; the \"eui.\" " + "should be followed by exactly 16 hexadecimal " + "digits", name); + for (i = strlen("eui."); name[i] != '\0'; i++) { + if (!isxdigit(name[i])) { + warn_fn("invalid character \"%c\" in target " + "name \"%s\"; allowed characters are 1-9 " + "and A-F", name[i], name); + break; + } + } + } else if (strncasecmp(name, "naa.", strlen("naa.")) == 0) { + if (strlen(name) > strlen("naa.") + 32) + warn_fn("invalid target name \"%s\"; the \"naa.\" " + "should be followed by at most 32 hexadecimal " + "digits", name); + for (i = strlen("naa."); name[i] != '\0'; i++) { + if (!isxdigit(name[i])) { + warn_fn("invalid character \"%c\" in target " + "name \"%s\"; allowed characters are 1-9 " + "and A-F", name[i], name); + break; + } + } + } else { + warn_fn("invalid target name \"%s\"; should start with " + "either \"iqn.\", \"eui.\", or \"naa.\"", + name); + } + return (true); +} diff --git a/usr.bin/iscsictl/Makefile b/usr.bin/iscsictl/Makefile --- a/usr.bin/iscsictl/Makefile +++ b/usr.bin/iscsictl/Makefile @@ -3,9 +3,10 @@ SRCS= iscsictl.c periphs.c parse.y token.l y.tab.h CFLAGS+= -I${.CURDIR} CFLAGS+= -I${SRCTOP}/sys/dev/iscsi +CFLAGS+= -I${SRCTOP}/lib/libiscsiutil MAN= iscsi.conf.5 iscsictl.8 -LIBADD= util xo +LIBADD= iscsiutil util xo YFLAGS+= -v LFLAGS+= -i diff --git a/usr.bin/iscsictl/iscsictl.h b/usr.bin/iscsictl/iscsictl.h --- a/usr.bin/iscsictl/iscsictl.h +++ b/usr.bin/iscsictl/iscsictl.h @@ -40,8 +40,6 @@ #define ISCSICTL_XO_VERSION "1" -#define MAX_NAME_LEN 223 - #define AUTH_METHOD_UNSPECIFIED 0 #define AUTH_METHOD_NONE 1 #define AUTH_METHOD_CHAP 2 @@ -103,7 +101,6 @@ void print_periphs(int session_id); -bool valid_iscsi_name(const char *name); int parse_enable(const char *enable); #endif /* !ISCSICTL_H */ diff --git a/usr.bin/iscsictl/iscsictl.c b/usr.bin/iscsictl/iscsictl.c --- a/usr.bin/iscsictl/iscsictl.c +++ b/usr.bin/iscsictl/iscsictl.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -122,38 +123,6 @@ return (name); } -static bool -valid_hex(const char ch) -{ - switch (ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case 'a': - case 'A': - case 'b': - case 'B': - case 'c': - case 'C': - case 'd': - case 'D': - case 'e': - case 'E': - case 'f': - case 'F': - return (true); - default: - return (false); - } -} - int parse_enable(const char *enable) { @@ -171,74 +140,6 @@ return (ENABLE_UNSPECIFIED); } -bool -valid_iscsi_name(const char *name) -{ - int i; - - if (strlen(name) >= MAX_NAME_LEN) { - xo_warnx("overlong name for \"%s\"; max length allowed " - "by iSCSI specification is %d characters", - name, MAX_NAME_LEN); - return (false); - } - - /* - * In the cases below, we don't return an error, just in case the admin - * was right, and we're wrong. - */ - if (strncasecmp(name, "iqn.", strlen("iqn.")) == 0) { - for (i = strlen("iqn."); name[i] != '\0'; i++) { - /* - * XXX: We should verify UTF-8 normalisation, as defined - * by 3.2.6.2: iSCSI Name Encoding. - */ - if (isalnum(name[i])) - continue; - if (name[i] == '-' || name[i] == '.' || name[i] == ':') - continue; - xo_warnx("invalid character \"%c\" in iSCSI name " - "\"%s\"; allowed characters are letters, digits, " - "'-', '.', and ':'", name[i], name); - break; - } - /* - * XXX: Check more stuff: valid date and a valid reversed domain. - */ - } else if (strncasecmp(name, "eui.", strlen("eui.")) == 0) { - if (strlen(name) != strlen("eui.") + 16) - xo_warnx("invalid iSCSI name \"%s\"; the \"eui.\" " - "should be followed by exactly 16 hexadecimal " - "digits", name); - for (i = strlen("eui."); name[i] != '\0'; i++) { - if (!valid_hex(name[i])) { - xo_warnx("invalid character \"%c\" in iSCSI " - "name \"%s\"; allowed characters are 1-9 " - "and A-F", name[i], name); - break; - } - } - } else if (strncasecmp(name, "naa.", strlen("naa.")) == 0) { - if (strlen(name) > strlen("naa.") + 32) - xo_warnx("invalid iSCSI name \"%s\"; the \"naa.\" " - "should be followed by at most 32 hexadecimal " - "digits", name); - for (i = strlen("naa."); name[i] != '\0'; i++) { - if (!valid_hex(name[i])) { - xo_warnx("invalid character \"%c\" in ISCSI " - "name \"%s\"; allowed characters are 1-9 " - "and A-F", name[i], name); - break; - } - } - } else { - xo_warnx("invalid iSCSI name \"%s\"; should start with " - "either \".iqn\", \"eui.\", or \"naa.\"", - name); - } - return (true); -} - void conf_verify(struct conf *conf) { @@ -257,7 +158,7 @@ xo_errx(1, "cannot specify TargetName for discovery " "sessions for target \"%s\"", targ->t_nickname); if (targ->t_name != NULL) { - if (valid_iscsi_name(targ->t_name) == false) + if (valid_iscsi_name(targ->t_name, xo_warnx) == false) xo_errx(1, "invalid target name \"%s\"", targ->t_name); } @@ -268,7 +169,7 @@ targ->t_nickname); if (targ->t_initiator_name == NULL) targ->t_initiator_name = default_initiator_name(); - if (valid_iscsi_name(targ->t_initiator_name) == false) + if (valid_iscsi_name(targ->t_initiator_name, xo_warnx) == false) xo_errx(1, "invalid initiator name \"%s\"", targ->t_initiator_name); if (targ->t_header_digest == DIGEST_UNSPECIFIED) @@ -1014,7 +915,7 @@ user, secret, enable); } else { if (Aflag != 0 && target != NULL) { - if (valid_iscsi_name(target) == false) + if (valid_iscsi_name(target, xo_warnx) == false) xo_errx(1, "invalid target name \"%s\"", target); } conf = conf_new(); diff --git a/usr.sbin/ctld/ctld.h b/usr.sbin/ctld/ctld.h --- a/usr.sbin/ctld/ctld.h +++ b/usr.sbin/ctld/ctld.h @@ -46,7 +46,6 @@ #define DEFAULT_CD_BLOCKSIZE 2048 #define MAX_LUNS 1024 -#define MAX_NAME_LEN 223 #define MAX_DATA_SEGMENT_LENGTH (128 * 1024) #define SOCKBUF_SIZE 1048576 @@ -387,7 +386,6 @@ void discovery(struct ctld_connection *conn); -bool valid_iscsi_name(const char *name); void set_timeout(int timeout, int fatal); #endif /* !CTLD_H */ diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c --- a/usr.sbin/ctld/ctld.c +++ b/usr.sbin/ctld/ctld.c @@ -1072,106 +1072,6 @@ return (0); } -static bool -valid_hex(const char ch) -{ - switch (ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case 'a': - case 'A': - case 'b': - case 'B': - case 'c': - case 'C': - case 'd': - case 'D': - case 'e': - case 'E': - case 'f': - case 'F': - return (true); - default: - return (false); - } -} - -bool -valid_iscsi_name(const char *name) -{ - int i; - - if (strlen(name) >= MAX_NAME_LEN) { - log_warnx("overlong name for target \"%s\"; max length allowed " - "by iSCSI specification is %d characters", - name, MAX_NAME_LEN); - return (false); - } - - /* - * In the cases below, we don't return an error, just in case the admin - * was right, and we're wrong. - */ - if (strncasecmp(name, "iqn.", strlen("iqn.")) == 0) { - for (i = strlen("iqn."); name[i] != '\0'; i++) { - /* - * XXX: We should verify UTF-8 normalisation, as defined - * by 3.2.6.2: iSCSI Name Encoding. - */ - if (isalnum(name[i])) - continue; - if (name[i] == '-' || name[i] == '.' || name[i] == ':') - continue; - log_warnx("invalid character \"%c\" in target name " - "\"%s\"; allowed characters are letters, digits, " - "'-', '.', and ':'", name[i], name); - break; - } - /* - * XXX: Check more stuff: valid date and a valid reversed domain. - */ - } else if (strncasecmp(name, "eui.", strlen("eui.")) == 0) { - if (strlen(name) != strlen("eui.") + 16) - log_warnx("invalid target name \"%s\"; the \"eui.\" " - "should be followed by exactly 16 hexadecimal " - "digits", name); - for (i = strlen("eui."); name[i] != '\0'; i++) { - if (!valid_hex(name[i])) { - log_warnx("invalid character \"%c\" in target " - "name \"%s\"; allowed characters are 1-9 " - "and A-F", name[i], name); - break; - } - } - } else if (strncasecmp(name, "naa.", strlen("naa.")) == 0) { - if (strlen(name) > strlen("naa.") + 32) - log_warnx("invalid target name \"%s\"; the \"naa.\" " - "should be followed by at most 32 hexadecimal " - "digits", name); - for (i = strlen("naa."); name[i] != '\0'; i++) { - if (!valid_hex(name[i])) { - log_warnx("invalid character \"%c\" in target " - "name \"%s\"; allowed characters are 1-9 " - "and A-F", name[i], name); - break; - } - } - } else { - log_warnx("invalid target name \"%s\"; should start with " - "either \"iqn.\", \"eui.\", or \"naa.\"", - name); - } - return (true); -} - struct pport * pport_new(struct kports *kports, const char *name, uint32_t ctl_port) { @@ -1389,8 +1289,7 @@ log_warnx("duplicated target \"%s\"", name); return (NULL); } - if (valid_iscsi_name(name) == false) { - log_warnx("target name \"%s\" is invalid", name); + if (valid_iscsi_name(name, log_warnx) == false) { return (NULL); } targ = calloc(1, sizeof(*targ)); diff --git a/usr.sbin/ctld/login.c b/usr.sbin/ctld/login.c --- a/usr.sbin/ctld/login.c +++ b/usr.sbin/ctld/login.c @@ -874,7 +874,7 @@ login_send_error(request, 0x02, 0x07); log_errx(1, "received Login PDU without InitiatorName"); } - if (valid_iscsi_name(initiator_name) == false) { + if (valid_iscsi_name(initiator_name, log_warnx) == false) { login_send_error(request, 0x02, 0x00); log_errx(1, "received Login PDU with invalid InitiatorName"); }