diff options
author | Chris Leech <cleech@redhat.com> | 2019-11-24 13:51:09 -0800 |
---|---|---|
committer | Chris Leech <cleech@redhat.com> | 2019-12-19 22:11:36 -0800 |
commit | d3daa7a2bc3f5bca874d3efd072b34a657c4d492 (patch) | |
tree | 9edc60f5574e36c869581a6e1d332bb94856ebd4 /libopeniscsiusr | |
parent | 4440e57a59c7f1c23bbfdcb10844017f478918b6 (diff) | |
download | open-iscsi-d3daa7a2bc3f5bca874d3efd072b34a657c4d492.tar.gz |
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.
Diffstat (limited to 'libopeniscsiusr')
-rw-r--r-- | libopeniscsiusr/default.c | 3 | ||||
-rw-r--r-- | libopeniscsiusr/idbm.c | 95 | ||||
-rw-r--r-- | libopeniscsiusr/idbm.h | 9 | ||||
-rw-r--r-- | libopeniscsiusr/idbm_fields.h | 1 |
4 files changed, 108 insertions, 0 deletions
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 d020e6c..05cb7f9 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, @@ -558,6 +592,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) @@ -565,8 +604,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); @@ -643,6 +688,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 " @@ -882,6 +968,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; @@ -944,6 +1037,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 3fd0864..cc90388 100644 --- a/libopeniscsiusr/idbm.h +++ b/libopeniscsiusr/idbm.h @@ -48,6 +48,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, @@ -92,6 +100,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" |