diff --git a/SOURCES/0001-Fix-bug-with-libopeniscsiusr.pc.patch b/SOURCES/0001-Fix-bug-with-libopeniscsiusr.pc.patch new file mode 100644 index 0000000..d2c3ea1 --- /dev/null +++ b/SOURCES/0001-Fix-bug-with-libopeniscsiusr.pc.patch @@ -0,0 +1,25 @@ +From 0c3953aebf69e23d7012a813ca2b35c5709acb02 Mon Sep 17 00:00:00 2001 +From: Patrick McCarty +Date: Wed, 8 Jan 2020 11:04:17 -0800 +Subject: [PATCH] Fix bug with libopeniscsiusr.pc + +The library name is libopeniscsiusr, so the -l linker option should be +`-lopeniscsiusr` instead of `-liscsiusr`. +--- + libopeniscsiusr/libopeniscsiusr.pc.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libopeniscsiusr/libopeniscsiusr.pc.in b/libopeniscsiusr/libopeniscsiusr.pc.in +index f0fb583..6bbee47 100644 +--- a/libopeniscsiusr/libopeniscsiusr.pc.in ++++ b/libopeniscsiusr/libopeniscsiusr.pc.in +@@ -5,5 +5,5 @@ Name: libopeniscsiusr + Version: __VERSION__ + Description: iSCSI userspace library + Requires: +-Libs: -L${libdir} -liscsiusr ++Libs: -L${libdir} -lopeniscsiusr + Cflags: -I${includedir} +-- +2.21.1 + diff --git a/SOURCES/0001-Revert-Out-of-bounds-read-Overrunning-array-of-8-2-b.patch b/SOURCES/0001-Revert-Out-of-bounds-read-Overrunning-array-of-8-2-b.patch new file mode 100644 index 0000000..1292efa --- /dev/null +++ b/SOURCES/0001-Revert-Out-of-bounds-read-Overrunning-array-of-8-2-b.patch @@ -0,0 +1,29 @@ +From e9c9117b7a84866366691110496984fc651e3e43 Mon Sep 17 00:00:00 2001 +From: Chris Leech +Date: Fri, 17 Jan 2020 13:42:10 -0800 +Subject: [PATCH 1/1] Revert "Out-of-bounds read: Overrunning array of 8 2-byte + elements" + +It's been reported that this breaks IPv6 discovery with qedi controllers + +This reverts commit af48f0d68db48cd492d0e27e046fc011be236fd3. +--- + iscsiuio/src/uip/ipv6.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/iscsiuio/src/uip/ipv6.c b/iscsiuio/src/uip/ipv6.c +index 5710199..05efa73 100644 +--- a/iscsiuio/src/uip/ipv6.c ++++ b/iscsiuio/src/uip/ipv6.c +@@ -521,7 +521,7 @@ static void ipv6_insert_protocol_chksum(struct ipv6_hdr *ipv6) + sum = 0; + ptr = (u16_t *)&ipv6->ipv6_src; + +- for (i = 0; i < sizeof(struct ipv6_addr); i += 2) { ++ for (i = 0; i < sizeof(struct ipv6_addr); i++) { + sum += HOST_TO_NET16(*ptr); + ptr++; + } +-- +2.21.1 + diff --git a/SOURCES/0001-configuration-support-for-CHAP-algorithms.patch b/SOURCES/0001-configuration-support-for-CHAP-algorithms.patch new file mode 100644 index 0000000..1e3dfeb --- /dev/null +++ b/SOURCES/0001-configuration-support-for-CHAP-algorithms.patch @@ -0,0 +1,661 @@ +From 9d36121534183195bd2892447ca07724013cef57 Mon Sep 17 00:00:00 2001 +From: Chris Leech +Date: Sun, 24 Nov 2019 13:51:09 -0800 +Subject: [PATCH 1/1] configuration support for CHAP algorithms + +Introduces support for preference lists in configuration files, and uses +that for the 'node.session.auth.chap_algs' setting. + +This is also re-used for discovery authentication, rather than have two +different configurations. +--- + etc/iscsid.conf | 7 ++ + libopeniscsiusr/default.c | 3 + + libopeniscsiusr/idbm.c | 95 +++++++++++++++++++++++++ + libopeniscsiusr/idbm.h | 9 +++ + libopeniscsiusr/idbm_fields.h | 1 + + usr/auth.c | 64 ++++++++++++----- + usr/auth.h | 3 + + usr/config.h | 1 + + usr/idbm.c | 126 ++++++++++++++++++++++++++++++---- + usr/idbm.h | 2 + + usr/idbm_fields.h | 1 + + usr/initiator.h | 1 + + usr/initiator_common.c | 2 + + usr/login.c | 11 +++ + 14 files changed, 294 insertions(+), 32 deletions(-) + +diff --git a/etc/iscsid.conf b/etc/iscsid.conf +index 2f3a28c..420145b 100644 +--- a/etc/iscsid.conf ++++ b/etc/iscsid.conf +@@ -57,6 +57,13 @@ node.leading_login = No + # to CHAP. The default is None. + #node.session.auth.authmethod = CHAP + ++# To configure which CHAP algorithms to enable set ++# node.session.auth.chap_algs to a comma seperated list. ++# The algorithms should be listen with most prefered first. ++# Valid values are MD5, SHA1, SHA256, and SHA3-256. ++# The default is MD5. ++#node.session.auth.chap_algs = SHA3-256,SHA256,SHA1,MD5 ++ + # To set a CHAP username and password for initiator + # authentication by the target(s), uncomment the following lines: + #node.session.auth.username = username +diff --git a/libopeniscsiusr/default.c b/libopeniscsiusr/default.c +index d01d892..d3b3da3 100644 +--- a/libopeniscsiusr/default.c ++++ b/libopeniscsiusr/default.c +@@ -78,6 +78,9 @@ void _default_node(struct iscsi_node *node) + node->session.initial_login_retry_max = DEF_INITIAL_LOGIN_RETRIES_MAX; + node->session.reopen_max = DEF_SESSION_REOPEN_MAX; + node->session.auth.authmethod = 0; ++ /* TYPE_INT_LIST fields should be initialized to ~0 to indicate unset values */ ++ memset(node->session.auth.chap_algs, ~0, sizeof(node->session.auth.chap_algs)); ++ node->session.auth.chap_algs[0] = ISCSI_AUTH_CHAP_ALG_MD5; + node->session.auth.password_length = 0; + node->session.auth.password_in_length = 0; + node->session.err_tmo.abort_timeout = DEF_ABORT_TIMEO; +diff --git a/libopeniscsiusr/idbm.c b/libopeniscsiusr/idbm.c +index 342aab5..d1fc03d 100644 +--- a/libopeniscsiusr/idbm.c ++++ b/libopeniscsiusr/idbm.c +@@ -73,6 +73,7 @@ + #define TYPE_INT32 6 + #define TYPE_INT64 7 + #define TYPE_BOOL 8 ++#define TYPE_INT_LIST 9 + #define MAX_KEYS 256 /* number of keys total(including CNX_MAX) */ + #define NAME_MAXVAL 128 /* the maximum length of key name */ + #define VALUE_MAXVAL 256 /* the maximum length of 223 bytes in the RFC. */ +@@ -248,6 +249,39 @@ do { \ + _n++; \ + } while(0) + ++#define ARRAY_LEN(x) ( sizeof(x) / sizeof((x)[0]) ) ++ ++/* Options list type, rather than matching a single value this populates an ++ * array with a list of values in user specified order. ++ * Requires a table matching config strings to values. ++ **/ ++#define _rec_int_list(_key, _recs, _org, _name, _show, _tbl, _n, _mod) \ ++do {\ ++ _recs[_n].type = TYPE_INT_LIST; \ ++ _strncpy(_recs[_n].name, _key, NAME_MAXVAL); \ ++ for (unsigned int _i = 0; _i < ARRAY_LEN(_org->_name); _i++) { \ ++ if (_org->_name[_i] != ~0UL) { \ ++ for (unsigned int _j = 0; _j < ARRAY_LEN(_tbl); _j++) { \ ++ if (_tbl[_j].value == _org->_name[_i]) { \ ++ strcat(_recs[_n].value, _tbl[_j].name); \ ++ strcat(_recs[_n].value, ","); \ ++ break; \ ++ } \ ++ } \ ++ } \ ++ } \ ++ /* delete traling ',' */ \ ++ if (strrchr(_recs[_n].value, ',')) \ ++ *strrchr(_recs[_n].value, ',') = '\0'; \ ++ _recs[_n].data = &_org->_name; \ ++ _recs[_n].data_len = sizeof(_org->_name); \ ++ _recs[_n].visible = _show; \ ++ _recs[_n].opts[0] = (void *)&_tbl; \ ++ _recs[_n].numopts = ARRAY_LEN(_tbl); \ ++ _recs[_n].can_modify = _mod; \ ++ _n++; \ ++} while(0) ++ + enum modify_mode { + _CANNOT_MODIFY, + _CAN_MODIFY, +@@ -557,6 +591,11 @@ void _idbm_node_print(struct iscsi_node *node, FILE *f, bool show_secret) + _idbm_recs_free(recs); + } + ++struct int_list_tbl { ++ const char *name; ++ unsigned int value; ++}; ++ + static int _idbm_rec_update_param(struct iscsi_context *ctx, + struct idbm_rec *recs, char *name, + char *value, int line_number) +@@ -564,8 +603,14 @@ static int _idbm_rec_update_param(struct iscsi_context *ctx, + int rc = LIBISCSI_OK; + int i = 0; + int j = 0; ++ int k = 0; + int passwd_done = 0; + char passwd_len[8]; ++ struct int_list_tbl *tbl = NULL; ++ char *tmp_value; ++ int *tmp_data; ++ bool *found; ++ char *token; + + assert(ctx != NULL); + assert(recs != NULL); +@@ -642,6 +687,47 @@ setup_passwd_len: + else + goto unknown_value; + goto updated; ++ case TYPE_INT_LIST: ++ if (!recs[i].data) ++ continue; ++ tbl = (void *)recs[i].opts[0]; ++ /* strsep is destructive, make a copy to work with */ ++ tmp_value = strdup(value); ++ k = 0; ++ tmp_data = malloc(recs[i].data_len); ++ memset(tmp_data, ~0, recs[i].data_len); ++ found = calloc(recs[i].numopts, sizeof(bool)); ++next_token: while ((token = strsep(&tmp_value, ", \n"))) { ++ if (!strlen(token)) ++ continue; ++ if ((k * (int)sizeof(int)) >= (recs[i].data_len)) { ++ _warn(ctx, "Too many values set for '%s'" ++ ", continuing without processing them all", ++ recs[i].name); ++ break; ++ } ++ for (j = 0; j < recs[i].numopts; j++) { ++ if (!strcmp(token, tbl[j].name)) { ++ if ((found[j])) { ++ _warn(ctx, "Ignoring repeated value '%s'" ++ " for '%s'", token, recs[i].name); ++ goto next_token; ++ } ++ ((unsigned *)tmp_data)[k++] = tbl[j].value; ++ found[j] = true; ++ goto next_token; ++ } ++ } ++ _warn(ctx, "Ignoring unknown value '%s'" ++ " for '%s'", token, recs[i].name); ++ } ++ memcpy(recs[i].data, tmp_data, recs[i].data_len); ++ free(tmp_value); ++ free(tmp_data); ++ tmp_value = NULL; ++ tmp_data = NULL; ++ token = NULL; ++ goto updated; + default: + unknown_value: + _error(ctx, "Got unknown data type %d " +@@ -881,6 +967,13 @@ void _idbm_free(struct idbm *db) + free(db); + } + ++static struct int_list_tbl chap_algs[] = { ++ { "MD5", ISCSI_AUTH_CHAP_ALG_MD5 }, ++ { "SHA1", ISCSI_AUTH_CHAP_ALG_SHA1 }, ++ { "SHA256", ISCSI_AUTH_CHAP_ALG_SHA256 }, ++ { "SHA3-256", ISCSI_AUTH_CHAP_ALG_SHA3_256 }, ++}; ++ + static void _idbm_node_rec_link(struct iscsi_node *node, struct idbm_rec *recs) + { + int num = 0; +@@ -943,6 +1036,8 @@ static void _idbm_node_rec_link(struct iscsi_node *node, struct idbm_rec *recs) + _rec_uint32(SESSION_PASSWORD_IN_LEN, recs, node, + session.auth.password_in_length, IDBM_HIDE, num, + _CAN_MODIFY); ++ _rec_int_list(SESSION_CHAP_ALGS, recs, node, session.auth.chap_algs, ++ IDBM_SHOW, chap_algs, num, _CAN_MODIFY); + _rec_int64(SESSION_REPLACEMENT_TMO, recs, node, + session.tmo.replacement_timeout, IDBM_SHOW, num, + _CAN_MODIFY); +diff --git a/libopeniscsiusr/idbm.h b/libopeniscsiusr/idbm.h +index c84d332..5a4d2fa 100644 +--- a/libopeniscsiusr/idbm.h ++++ b/libopeniscsiusr/idbm.h +@@ -49,6 +49,14 @@ enum iscsi_auth_method { + ISCSI_AUTH_METHOD_CHAP, + }; + ++enum iscsi_chap_algs { ++ ISCSI_AUTH_CHAP_ALG_MD5 = 5, ++ ISCSI_AUTH_CHAP_ALG_SHA1 = 6, ++ ISCSI_AUTH_CHAP_ALG_SHA256 = 7, ++ ISCSI_AUTH_CHAP_ALG_SHA3_256 = 8, ++ AUTH_CHAP_ALG_MAX_COUNT = 5, ++}; ++ + enum iscsi_startup_type { + ISCSI_STARTUP_MANUAL, + ISCSI_STARTUP_AUTOMATIC, +@@ -93,6 +101,7 @@ struct iscsi_auth_config { + char username_in[AUTH_STR_MAX_LEN]; + unsigned char password_in[AUTH_STR_MAX_LEN]; + uint32_t password_in_length; ++ unsigned int chap_algs[AUTH_CHAP_ALG_MAX_COUNT]; + }; + + /* all TCP options go in this structure. +diff --git a/libopeniscsiusr/idbm_fields.h b/libopeniscsiusr/idbm_fields.h +index 29a2090..8bf17b0 100644 +--- a/libopeniscsiusr/idbm_fields.h ++++ b/libopeniscsiusr/idbm_fields.h +@@ -120,6 +120,7 @@ + #define SESSION_USERNAME_IN "node.session.auth.username_in" + #define SESSION_PASSWORD_IN "node.session.auth.password_in" + #define SESSION_PASSWORD_IN_LEN "node.session.auth.password_in_length" ++#define SESSION_CHAP_ALGS "node.session.auth.chap_algs" + #define SESSION_REPLACEMENT_TMO "node.session.timeo.replacement_timeout" + #define SESSION_ABORT_TMO "node.session.err_timeo.abort_timeout" + #define SESSION_LU_RESET_TMO "node.session.err_timeo.lu_reset_timeout" +diff --git a/usr/auth.c b/usr/auth.c +index 5c819c2..a222c53 100644 +--- a/usr/auth.c ++++ b/usr/auth.c +@@ -1806,7 +1806,7 @@ acl_chk_chap_alg_list(unsigned int option_count, const int *option_list) + return 0; + } + +-static int ++int + acl_set_chap_alg_list(struct iscsi_acl *client, unsigned int option_count, + const int *option_list) + { +@@ -1819,22 +1819,54 @@ acl_set_chap_alg_list(struct iscsi_acl *client, unsigned int option_count, + } + + int +-acl_init_chap_digests(int *value_list) { ++acl_init_chap_digests(int *value_list, unsigned *chap_algs, int conf_count) { + EVP_MD_CTX *context = EVP_MD_CTX_new(); + int i = 0; + +- if (EVP_DigestInit_ex(context, EVP_sha3_256(), NULL)) { +- value_list[i++] = AUTH_CHAP_ALG_SHA3_256; +- } +- if (EVP_DigestInit_ex(context, EVP_sha256(), NULL)) { +- value_list[i++] = AUTH_CHAP_ALG_SHA256; +- } +- if (EVP_DigestInit_ex(context, EVP_sha1(), NULL)) { +- value_list[i++] = AUTH_CHAP_ALG_SHA1; +- } +- if (EVP_DigestInit_ex(context, EVP_md5(), NULL)) { +- value_list[i++] = AUTH_CHAP_ALG_MD5; ++ for (int j = 0; j < conf_count; j++) { ++ switch (chap_algs[j]) { ++ case AUTH_CHAP_ALG_MD5: ++ if (EVP_DigestInit_ex(context, EVP_md5(), NULL)) { ++ value_list[i++] = AUTH_CHAP_ALG_MD5; ++ } else { ++ log_warning("Ignoring CHAP algorthm request for " ++ "MD5 due to crypto lib configuration"); ++ } ++ break; ++ case AUTH_CHAP_ALG_SHA1: ++ if (EVP_DigestInit_ex(context, EVP_sha1(), NULL)) { ++ value_list[i++] = AUTH_CHAP_ALG_SHA1; ++ } else { ++ log_warning("Ignoring CHAP algorthm request for " ++ "SHA1 due to crypto lib configuration"); ++ } ++ break; ++ case AUTH_CHAP_ALG_SHA256: ++ if (EVP_DigestInit_ex(context, EVP_sha256(), NULL)) { ++ value_list[i++] = AUTH_CHAP_ALG_SHA256; ++ } else { ++ log_warning("Ignoring CHAP algorthm request for " ++ "SHA256 due to crypto lib configuration"); ++ } ++ break; ++ case AUTH_CHAP_ALG_SHA3_256: ++ if (EVP_DigestInit_ex(context, EVP_sha3_256(), NULL)) { ++ value_list[i++] = AUTH_CHAP_ALG_SHA3_256; ++ } else { ++ log_warning("Ignoring CHAP algorthm request for " ++ "SHA3-256 due to crypto lib configuration"); ++ } ++ break; ++ case ~0: ++ /* unset value in array, just ignore */ ++ break; ++ default: ++ log_warning("Ignoring unknown CHAP algorithm request " ++ "'%d'", chap_algs[j]); ++ break; ++ } + } ++ + return i; + } + +@@ -1926,12 +1958,6 @@ acl_init(int node_type, int buf_desc_count, struct auth_buffer_desc *buff_desc) + return AUTH_STATUS_ERROR; + } + +- if (acl_set_chap_alg_list(client, acl_init_chap_digests(value_list), +- value_list) != AUTH_STATUS_NO_ERROR) { +- client->phase = AUTH_PHASE_ERROR; +- return AUTH_STATUS_ERROR; +- } +- + return AUTH_STATUS_NO_ERROR; + } + +diff --git a/usr/auth.h b/usr/auth.h +index f6dbbe4..16cdb24 100644 +--- a/usr/auth.h ++++ b/usr/auth.h +@@ -271,6 +271,9 @@ extern int acl_send_transit_bit(struct iscsi_acl *client, int *value); + extern int acl_set_user_name(struct iscsi_acl *client, const char *username); + extern int acl_set_passwd(struct iscsi_acl *client, + const unsigned char *pw_data, unsigned int pw_len); ++extern int acl_set_chap_alg_list(struct iscsi_acl *client, unsigned int option_count, ++ const int *option_list); ++extern int acl_init_chap_digests(int *value_list, unsigned int *chap_algs, int count); + extern int acl_set_auth_rmt(struct iscsi_acl *client, int auth_rmt); + extern int acl_set_ip_sec(struct iscsi_acl *client, int ip_sec); + extern int acl_get_dbg_status(struct iscsi_acl *client, int *value); +diff --git a/usr/config.h b/usr/config.h +index 250879d..79059ec 100644 +--- a/usr/config.h ++++ b/usr/config.h +@@ -58,6 +58,7 @@ struct iscsi_auth_config { + char username_in[AUTH_STR_MAX_LEN]; + unsigned char password_in[AUTH_STR_MAX_LEN]; + unsigned int password_in_length; ++ unsigned int chap_algs[AUTH_CHAP_ALG_MAX_COUNT]; + }; + + /* all per-connection timeouts go in this structure. +diff --git a/usr/idbm.c b/usr/idbm.c +index 0c6870c..749203a 100644 +--- a/usr/idbm.c ++++ b/usr/idbm.c +@@ -51,6 +51,8 @@ + + static struct idbm *db; + ++#define ARRAY_LEN(x) ( sizeof(x) / sizeof((x)[0]) ) ++ + #define __recinfo_str(_key, _info, _rec, _name, _show, _n, _mod) do { \ + _info[_n].type = TYPE_STR; \ + strlcpy(_info[_n].name, _key, NAME_MAXVAL); \ +@@ -165,6 +167,42 @@ static struct idbm *db; + _n++; \ + } while(0) + ++#define __recinfo_int_list(_key,_info,_rec,_name,_show,_tbl,_n,_mod) do { \ ++ _info[_n].type = TYPE_INT_LIST; \ ++ strlcpy(_info[_n].name, _key, NAME_MAXVAL); \ ++ for(int _i = 0; _i < ARRAY_LEN(_rec->_name); _i++) { \ ++ if (_rec->_name[_i] != ~0) { \ ++ for (int _j = 0; _j < ARRAY_LEN(_tbl); _j++) { \ ++ if (_tbl[_j].value == _rec->_name[_i]) { \ ++ strcat(_info[_n].value, _tbl[_j].name); \ ++ strcat(_info[_n].value, ","); \ ++ break; \ ++ } \ ++ } \ ++ } \ ++ } \ ++ /* delete trailing ',' */ \ ++ if (strrchr(_info[_n].value, ',')) \ ++ *strrchr(_info[_n].value, ',') = '\0'; \ ++ _info[_n].data = &_rec->_name; \ ++ _info[_n].data_len = sizeof(_rec->_name); \ ++ _info[_n].visible = _show; \ ++ _info[_n].opts[0] = (void *)&_tbl; \ ++ _info[_n].numopts = ARRAY_LEN(_tbl); \ ++ _info[_n].can_modify = _mod; \ ++ _n++; \ ++} while (0) ++ ++static struct int_list_tbl { ++ const char *name; ++ int value; ++} chap_algs [] = { ++ { "MD5", AUTH_CHAP_ALG_MD5 }, ++ { "SHA1", AUTH_CHAP_ALG_SHA1 }, ++ { "SHA256", AUTH_CHAP_ALG_SHA256 }, ++ { "SHA3-256", AUTH_CHAP_ALG_SHA3_256 }, ++}; ++ + static int idbm_remove_disc_to_node_link(node_rec_t *rec, char *portal); + + static void +@@ -199,6 +237,10 @@ idbm_recinfo_discovery(discovery_rec_t *r, recinfo_t *ri) + __recinfo_int(DISC_ST_PASSWORD_IN_LEN, ri, r, + u.sendtargets.auth.password_in_length, IDBM_HIDE, + num, 1); ++ /* reusing SESSION_CHAP_ALGS */ ++ __recinfo_int_list(SESSION_CHAP_ALGS, ri, r, ++ u.sendtargets.auth.chap_algs, ++ IDBM_SHOW, chap_algs, num, 1); + __recinfo_int(DISC_ST_LOGIN_TMO, ri, r, + u.sendtargets.conn_timeo.login_timeout, + IDBM_SHOW, num, 1); +@@ -431,6 +473,8 @@ idbm_recinfo_node(node_rec_t *r, recinfo_t *ri) + session.auth.password_in, IDBM_MASKED, num, 1); + __recinfo_int(SESSION_PASSWORD_IN_LEN, ri, r, + session.auth.password_in_length, IDBM_HIDE, num, 1); ++ __recinfo_int_list(SESSION_CHAP_ALGS, ri, r, ++ session.auth.chap_algs, IDBM_SHOW, chap_algs, num, 1); + __recinfo_int(SESSION_REPLACEMENT_TMO, ri, r, + session.timeo.replacement_timeout, + IDBM_SHOW, num, 1); +@@ -940,6 +984,9 @@ idbm_discovery_setup_defaults(discovery_rec_t *rec, discovery_type_e type) + rec->u.sendtargets.auth.authmethod = 0; + rec->u.sendtargets.auth.password_length = 0; + rec->u.sendtargets.auth.password_in_length = 0; ++ /* TYPE_INT_LIST fields should be initialized to ~0 to indicate unset values */ ++ memset(rec->u.sendtargets.auth.chap_algs, ~0, sizeof(rec->u.sendtargets.auth.chap_algs)); ++ rec->u.sendtargets.auth.chap_algs[0] = AUTH_CHAP_ALG_MD5; + rec->u.sendtargets.conn_timeo.login_timeout=15; + rec->u.sendtargets.conn_timeo.auth_timeout = 45; + rec->u.sendtargets.conn_timeo.active_timeout=30; +@@ -973,59 +1020,109 @@ int idbm_rec_update_param(recinfo_t *info, char *name, char *value, + int i; + int passwd_done = 0; + char passwd_len[8]; ++ char *tmp_value, *token; ++ bool *found; ++ int *tmp_data; + + setup_passwd_len: + for (i=0; i '%s'", name, + info[i].value, value); + /* parse recinfo by type */ +- if (info[i].type == TYPE_INT) { ++ switch (info[i].type) { ++ case TYPE_INT: + if (!info[i].data) + continue; + + *(int*)info[i].data = + strtoul(value, NULL, 10); + goto updated; +- } else if (info[i].type == TYPE_UINT8) { ++ case TYPE_UINT8: + if (!info[i].data) + continue; + + *(uint8_t *)info[i].data = + strtoul(value, NULL, 10); + goto updated; +- } else if (info[i].type == TYPE_UINT16) { ++ case TYPE_UINT16: + if (!info[i].data) + continue; + + *(uint16_t *)info[i].data = + strtoul(value, NULL, 10); + goto updated; +- } else if (info[i].type == TYPE_UINT32) { ++ case TYPE_UINT32: + if (!info[i].data) + continue; + + *(uint32_t *)info[i].data = + strtoul(value, NULL, 10); + goto updated; +- } else if (info[i].type == TYPE_STR) { ++ case TYPE_STR: + if (!info[i].data) + continue; + + strlcpy((char*)info[i].data, + value, info[i].data_len); + goto updated; +- } +- for (j=0; j= (info[i].data_len)) { ++ log_warning("Too many values set for '%s'" ++ ", continuing without processing them all", ++ info[i].name); ++ break; ++ } ++ for (j = 0; j < info[i].numopts; j++) { ++ if (!strcmp(token, tbl[j].name)) { ++ if ((found[j])) { ++ log_warning("Ignoring repeated " ++ "value '%s' " ++ "for '%s'", token, ++ info[i].name); ++ goto next_token; ++ } ++ ((int*)tmp_data)[k++] = tbl[j].value; ++ found[j] = true; ++ goto next_token; ++ } ++ } ++ log_warning("Ignoring unknown value '%s'" ++ " for '%s'", token, info[i].name); + } ++ memcpy(info[i].data, tmp_data, info[i].data_len); ++ free(tmp_value); ++ free(tmp_data); ++ tmp_value = NULL; ++ tmp_data = NULL; ++ token = NULL; ++ goto updated; + } + if (line_number) { + log_warning("config file line %d contains " +@@ -3098,6 +3195,9 @@ void idbm_node_setup_defaults(node_rec_t *rec) + rec->session.initial_login_retry_max = DEF_INITIAL_LOGIN_RETRIES_MAX; + rec->session.reopen_max = DEF_SESSION_REOPEN_MAX; + rec->session.auth.authmethod = 0; ++ /* TYPE_INT_LIST fields should be initialized to ~0 to indicate unset values */ ++ memset(rec->session.auth.chap_algs, ~0, sizeof(rec->session.auth.chap_algs)); ++ rec->session.auth.chap_algs[0] = AUTH_CHAP_ALG_MD5; + rec->session.auth.password_length = 0; + rec->session.auth.password_in_length = 0; + rec->session.err_timeo.abort_timeout = DEF_ABORT_TIMEO; +diff --git a/usr/idbm.h b/usr/idbm.h +index c6982e4..d1a7f63 100644 +--- a/usr/idbm.h ++++ b/usr/idbm.h +@@ -46,6 +46,8 @@ + #define TYPE_UINT8 3 + #define TYPE_UINT16 4 + #define TYPE_UINT32 5 ++#define TYPE_INT_LIST 6 ++ + #define MAX_KEYS 256 /* number of keys total(including CNX_MAX) */ + #define NAME_MAXVAL 128 /* the maximum length of key name */ + #define VALUE_MAXVAL 256 /* the maximum length of 223 bytes in the RFC. */ +diff --git a/usr/idbm_fields.h b/usr/idbm_fields.h +index 142c7ae..4a967fc 100644 +--- a/usr/idbm_fields.h ++++ b/usr/idbm_fields.h +@@ -30,6 +30,7 @@ + #define SESSION_USERNAME_IN "node.session.auth.username_in" + #define SESSION_PASSWORD_IN "node.session.auth.password_in" + #define SESSION_PASSWORD_IN_LEN "node.session.auth.password_in_length" ++#define SESSION_CHAP_ALGS "node.session.auth.chap_algs" + #define SESSION_REPLACEMENT_TMO "node.session.timeo.replacement_timeout" + #define SESSION_ABORT_TMO "node.session.err_timeo.abort_timeout" + #define SESSION_LU_RESET_TMO "node.session.err_timeo.lu_reset_timeout" +diff --git a/usr/initiator.h b/usr/initiator.h +index eccafb9..6a49ea6 100644 +--- a/usr/initiator.h ++++ b/usr/initiator.h +@@ -243,6 +243,7 @@ typedef struct iscsi_session { + char username_in[AUTH_STR_MAX_LEN]; + uint8_t password_in[AUTH_STR_MAX_LEN]; + int password_in_length; ++ unsigned int chap_algs[AUTH_CHAP_ALG_MAX_COUNT]; + iscsi_conn_t conn[ISCSI_CONN_MAX]; + uint64_t param_mask; + +diff --git a/usr/initiator_common.c b/usr/initiator_common.c +index 790f13d..81da8fd 100644 +--- a/usr/initiator_common.c ++++ b/usr/initiator_common.c +@@ -94,6 +94,8 @@ int iscsi_setup_authentication(struct iscsi_session *session, + memcpy(session->password_in, auth_cfg->password_in, + session->password_in_length); + ++ memcpy(session->chap_algs, auth_cfg->chap_algs, sizeof(auth_cfg->chap_algs)); ++ + if (session->password_length || session->password_in_length) { + /* setup the auth buffers */ + session->auth_buffers[0].address = &session->auth_client_block; +diff --git a/usr/login.c b/usr/login.c +index d7dad21..1251e61 100644 +--- a/usr/login.c ++++ b/usr/login.c +@@ -1262,6 +1262,17 @@ check_for_authentication(iscsi_session_t *session, + goto end; + } + ++ int value_list[AUTH_CHAP_ALG_MAX_COUNT]; ++ ++ if (acl_set_chap_alg_list(auth_client, ++ acl_init_chap_digests(value_list, ++ session->chap_algs, ++ AUTH_CHAP_ALG_MAX_COUNT), ++ value_list) != AUTH_STATUS_NO_ERROR) { ++ log_error("Couldn't set CHAP algorithm list"); ++ goto end; ++ } ++ + if (acl_set_ip_sec(auth_client, 1) != AUTH_STATUS_NO_ERROR) { + log_error("Couldn't set IPSec"); + goto end; +-- +2.21.1 + diff --git a/SOURCES/0001-enable-all-CHAP-digest-functions-by-default.patch b/SOURCES/0001-enable-all-CHAP-digest-functions-by-default.patch new file mode 100644 index 0000000..804cb2f --- /dev/null +++ b/SOURCES/0001-enable-all-CHAP-digest-functions-by-default.patch @@ -0,0 +1,25 @@ +From a89f547c29f5d3f61a10eb1847b992f9f7f9a65a Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Wed, 8 Jan 2020 14:00:35 -0800 +Subject: [PATCH 1/1] enable all CHAP digest functions by default + +--- + etc/iscsid.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/etc/iscsid.conf b/etc/iscsid.conf +index 420145b..c1960e5 100644 +--- a/etc/iscsid.conf ++++ b/etc/iscsid.conf +@@ -62,7 +62,7 @@ node.leading_login = No + # The algorithms should be listen with most prefered first. + # Valid values are MD5, SHA1, SHA256, and SHA3-256. + # The default is MD5. +-#node.session.auth.chap_algs = SHA3-256,SHA256,SHA1,MD5 ++node.session.auth.chap_algs = SHA3-256,SHA256,SHA1,MD5 + + # To set a CHAP username and password for initiator + # authentication by the target(s), uncomment the following lines: +-- +2.21.1 + diff --git a/SOURCES/0022-use-Red-Hat-version-string-to-match-RPM-package-vers.patch b/SOURCES/0022-use-Red-Hat-version-string-to-match-RPM-package-vers.patch index 67d004b..2717913 100644 --- a/SOURCES/0022-use-Red-Hat-version-string-to-match-RPM-package-vers.patch +++ b/SOURCES/0022-use-Red-Hat-version-string-to-match-RPM-package-vers.patch @@ -16,7 +16,7 @@ index 615f533..a1f6cc2 100644 * some other maintainer could merge a patch without going through us */ -#define ISCSI_VERSION_STR "2.0-878" -+#define ISCSI_VERSION_STR "6.2.0.878-0" ++#define ISCSI_VERSION_STR "6.2.0.878-2" #define ISCSI_VERSION_FILE "/sys/module/scsi_transport_iscsi/version" #endif diff --git a/SPECS/iscsi-initiator-utils.spec b/SPECS/iscsi-initiator-utils.spec index 480545b..003550e 100644 --- a/SPECS/iscsi-initiator-utils.spec +++ b/SPECS/iscsi-initiator-utils.spec @@ -13,7 +13,7 @@ Summary: iSCSI daemon and utility programs Name: iscsi-initiator-utils Version: 6.%{open_iscsi_version}.%{open_iscsi_build} -Release: 0.git%{shortcommit0}%{?dist} +Release: 4.git%{shortcommit0}%{?dist} Group: System Environment/Daemons License: GPLv2+ URL: http://www.open-iscsi.org @@ -43,6 +43,10 @@ Patch0019: 0019-Coverity-scan-fixes.patch Patch0020: 0020-fix-upstream-build-breakage-of-iscsiuio-LDFLAGS.patch Patch0021: 0021-improve-systemd-service-files-for-boot-session-handl.patch Patch0022: 0022-use-Red-Hat-version-string-to-match-RPM-package-vers.patch +Patch0023: 0001-configuration-support-for-CHAP-algorithms.patch +Patch0024: 0001-Fix-bug-with-libopeniscsiusr.pc.patch +Patch0025: 0001-enable-all-CHAP-digest-functions-by-default.patch +Patch0026: 0001-Revert-Out-of-bounds-read-Overrunning-array-of-8-2-b.patch BuildRequires: flex bison doxygen kmod-devel systemd-units BuildRequires: autoconf automake libtool libmount-devel openssl-devel @@ -108,7 +112,7 @@ developing applications that use %{name}. %{?python_provide:%python_provide python2-%{name}} Summary: Python %{python2_version} bindings to %{name} Group: Development/Libraries - +Requires: %{name} = %{version}-%{release} BuildRequires: python2-devel BuildRequires: python2-setuptools @@ -121,7 +125,7 @@ libiscsi interface for interacting with %{name} %{?python_provide:%python_provide python3-%{name}} Summary: Python %{python3_version} bindings to %{name} Group: Development/Libraries - +Requires: %{name} = %{version}-%{release} BuildRequires: python3-devel BuildRequires: python3-setuptools @@ -181,6 +185,7 @@ touch $RPM_BUILD_ROOT/var/lock/iscsi/lock %{__install} -d $RPM_BUILD_ROOT%{_unitdir} %{__install} -pm 644 etc/systemd/iscsi.service $RPM_BUILD_ROOT%{_unitdir} +%{__install} -pm 644 etc/systemd/iscsi-onboot.service $RPM_BUILD_ROOT%{_unitdir} %{__install} -pm 644 etc/systemd/iscsi-shutdown.service $RPM_BUILD_ROOT%{_unitdir} %{__install} -pm 644 etc/systemd/iscsid.service $RPM_BUILD_ROOT%{_unitdir} %{__install} -pm 644 etc/systemd/iscsid.socket $RPM_BUILD_ROOT%{_unitdir} @@ -217,7 +222,7 @@ popd %post /sbin/ldconfig -%systemd_post iscsi.service iscsi-shutdown.service iscsid.service iscsid.socket +%systemd_post iscsi.service iscsi-onboot.service iscsi-shutdown.service iscsid.service iscsid.socket if [ $1 -eq 1 ]; then if [ ! -f %{_sysconfdir}/iscsi/initiatorname.iscsi ]; then @@ -225,6 +230,7 @@ if [ $1 -eq 1 ]; then fi # enable socket activation and persistant session startup by default /bin/systemctl enable iscsi.service >/dev/null 2>&1 || : + /bin/systemctl enable iscsi-onboot.service >/dev/null 2>&1 || : /bin/systemctl enable iscsid.socket >/dev/null 2>&1 || : fi @@ -236,14 +242,14 @@ if [ $1 -eq 1 ]; then fi %preun -%systemd_preun iscsi.service iscsi-shutdown.service iscsid.service iscsiuio.service iscsid.socket iscsiuio.socket +%systemd_preun iscsi.service iscsi-onboot.service iscsi-shutdown.service iscsid.service iscsiuio.service iscsid.socket iscsiuio.socket %preun iscsiuio %systemd_preun iscsiuio.service iscsiuio.socket %postun /sbin/ldconfig -%systemd_postun iscsi.service iscsi-shutdown.service iscsid.service iscsiuio.service iscsid.socket iscsiuio.socket +%systemd_postun iscsi.service iscsi-onboot.service iscsi-shutdown.service iscsid.service iscsiuio.service iscsid.socket iscsiuio.socket %postun iscsiuio %systemd_postun iscsiuio.service iscsiuio.socket @@ -273,6 +279,11 @@ if [ $1 -gt 0 ]; then systemctl start iscsi-shutdown.service >/dev/null 2>&1 || : fi +%triggerpostun -- iscsi-initiator-utils < 6.2.0.878-4 +# added in 6.2.0.878-0, needs to be enabled during an upgrade +if [ $1 -gt 0 ]; then + /bin/systemctl enable iscsi-onboot.service >/dev/null 2>&1 || : +fi %files %doc README @@ -286,6 +297,7 @@ fi %ghost %{_var}/lock/iscsi %ghost %{_var}/lock/iscsi/lock %{_unitdir}/iscsi.service +%{_unitdir}/iscsi-onboot.service %{_unitdir}/iscsi-shutdown.service %{_unitdir}/iscsid.service %{_unitdir}/iscsid.socket @@ -344,6 +356,18 @@ fi %{python3_sitearch}/* %changelog +* Tue Mar 24 2020 Chris Leech - 6.2.0.878-3.gitd791ce0 +- 1801577 new service file not enabled on upgrade, spec change to use triggers for that + +* Mon Feb 17 2020 Chris Leech - 6.2.0.878-3.gitd791ce0 +- 1801577 missing spec file changes from 6.2.0.878-0 causing iSCSI boot regression + +* Mon Jan 20 2020 Chris Leech - 6.2.0.878-2.gitd791ce0 +- 1786015 fix IPv6 discovery regression in iscsiuio + +* Wed Jan 08 2020 Chris Leech - 6.2.0.878-1.gitd791ce0 +- 1788233 added node.session.auth.chap_algs configuration setting + * Thu Nov 07 2019 Chris Leech - 6.2.0.878-0.gitd791ce0 - 1761940 iSCSI CHAP authentication not function with FIPS enabled - Service file improvements forward ported from RHEL 7.8