Skip to content

Commit 9c4a34b

Browse files
dwsuseigaw
authored andcommitted
json: move keystore operations out of the JSON parser
The JSON parser is loading the keys into the kernel. This is a privileged operations (root) thus the parser will fail for a normal user. This also makes 'nvme list' etc fail for normal users. Furthermore, we try to insert each time the keys into the keystore when libnvme parses the JSON configuration. Let's move the key import operations to the connect call path where we need the right permission. A nice side benefit is that we also are able to pass in a configured key. The export feature will be added back later. Signed-off-by: Daniel Wagner <[email protected]>
1 parent c5a9371 commit 9c4a34b

4 files changed

Lines changed: 162 additions & 113 deletions

File tree

src/nvme/fabrics.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,9 @@ static int build_options(nvme_host_t h, nvme_ctrl_t c, char **argstr)
552552
const char *hostnqn, *hostid, *hostkey, *ctrlkey;
553553
bool discover = false, discovery_nqn = false;
554554
nvme_root_t r = h->r;
555+
long keyring_id = 0;
556+
long key_id = 0;
557+
int ret;
555558

556559
if (!transport) {
557560
nvme_msg(h->r, LOG_ERR, "need a transport (-t) argument\n");
@@ -573,19 +576,37 @@ static int build_options(nvme_host_t h, nvme_ctrl_t c, char **argstr)
573576
errno = ENOMEM;
574577
return -1;
575578
}
579+
576580
if (!strcmp(nvme_ctrl_get_subsysnqn(c), NVME_DISC_SUBSYS_NAME)) {
577581
nvme_ctrl_set_discovery_ctrl(c, true);
578582
nvme_ctrl_set_unique_discovery_ctrl(c, false);
579583
discovery_nqn = true;
580584
}
585+
581586
if (nvme_ctrl_is_discovery_ctrl(c))
582587
discover = true;
588+
583589
hostnqn = nvme_host_get_hostnqn(h);
584590
hostid = nvme_host_get_hostid(h);
585591
hostkey = nvme_host_get_dhchap_key(h);
586592
if (!hostkey)
587593
hostkey = nvme_ctrl_get_dhchap_host_key(c);
594+
588595
ctrlkey = nvme_ctrl_get_dhchap_key(c);
596+
597+
ret = __nvme_import_keys_from_config(h, c, &keyring_id, &key_id);
598+
if (ret) {
599+
errno = -ret;
600+
return -1;
601+
}
602+
603+
if (key_id == 0) {
604+
if (cfg->tls_configured_key)
605+
key_id = cfg->tls_configured_key;
606+
else
607+
key_id = cfg->tls_key;
608+
}
609+
589610
if (add_argument(r, argstr, transport, transport) ||
590611
add_argument(r, argstr, traddr,
591612
nvme_ctrl_get_traddr(c)) ||
@@ -627,9 +648,9 @@ static int build_options(nvme_host_t h, nvme_ctrl_t c, char **argstr)
627648
cfg->fast_io_fail_tmo, false)) ||
628649
(strcmp(transport, "loop") &&
629650
add_int_argument(r, argstr, tos, cfg->tos, true)) ||
630-
add_int_argument(r, argstr, keyring, cfg->keyring, false) ||
651+
add_int_argument(r, argstr, keyring, keyring_id, false) ||
631652
(!strcmp(transport, "tcp") &&
632-
add_int_argument(r, argstr, tls_key, cfg->tls_key, false)) ||
653+
add_int_argument(r, argstr, tls_key, key_id, false)) ||
633654
add_bool_argument(r, argstr, duplicate_connect,
634655
cfg->duplicate_connect) ||
635656
add_bool_argument(r, argstr, disable_sqflow,

src/nvme/json.c

Lines changed: 48 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -25,62 +25,10 @@
2525
#define JSON_UPDATE_BOOL_OPTION(c, k, a, o) \
2626
if (!strcmp(# a, k ) && !c->a) c->a = json_object_get_boolean(o);
2727

28-
static void json_import_nvme_tls_key(nvme_ctrl_t c, const char *keyring_str,
29-
const char *encoded_key)
30-
{
31-
struct nvme_fabrics_config *cfg = nvme_ctrl_get_config(c);
32-
const char *hostnqn = nvme_host_get_hostnqn(c->s->h);
33-
const char *subsysnqn = nvme_ctrl_get_subsysnqn(c);
34-
int key_len;
35-
unsigned int hmac;
36-
long key_id;
37-
_cleanup_free_ unsigned char *key_data = NULL;
38-
39-
if (!hostnqn || !subsysnqn) {
40-
nvme_msg(NULL, LOG_ERR, "Invalid NQNs (%s, %s)\n",
41-
hostnqn, subsysnqn);
42-
return;
43-
}
44-
key_data = nvme_import_tls_key(encoded_key, &key_len, &hmac);
45-
if (!key_data) {
46-
nvme_msg(NULL, LOG_ERR, "Failed to decode TLS Key '%s'\n",
47-
encoded_key);
48-
return;
49-
}
50-
key_id = nvme_insert_tls_key_versioned(keyring_str, "psk",
51-
hostnqn, subsysnqn,
52-
0, hmac, key_data, key_len);
53-
if (key_id <= 0)
54-
nvme_msg(NULL, LOG_ERR, "Failed to insert TLS KEY, error %d\n",
55-
errno);
56-
else {
57-
cfg->tls_key = key_id;
58-
cfg->tls = true;
59-
}
60-
}
61-
62-
static void json_export_nvme_tls_key(long keyring_id, long tls_key,
63-
struct json_object *obj)
64-
{
65-
int key_len;
66-
_cleanup_free_ unsigned char *key_data = NULL;
67-
68-
key_data = nvme_read_key(keyring_id, tls_key, &key_len);
69-
if (key_data) {
70-
_cleanup_free_ char *tls_str = NULL;
71-
72-
tls_str = nvme_export_tls_key(key_data, key_len);
73-
if (tls_str)
74-
json_object_object_add(obj, "tls_key",
75-
json_object_new_string(tls_str));
76-
}
77-
}
78-
7928
static void json_update_attributes(nvme_ctrl_t c,
8029
struct json_object *ctrl_obj)
8130
{
8231
struct nvme_fabrics_config *cfg = nvme_ctrl_get_config(c);
83-
const char *keyring_str = NULL, *encoded_key = NULL;
8432

8533
json_object_object_foreach(ctrl_obj, key_str, val_obj) {
8634
JSON_UPDATE_INT_OPTION(cfg, key_str,
@@ -120,31 +68,18 @@ static void json_update_attributes(nvme_ctrl_t c,
12068
if (!strcmp("discovery", key_str) &&
12169
!nvme_ctrl_is_discovery_ctrl(c))
12270
nvme_ctrl_set_discovery_ctrl(c, true);
123-
/*
124-
* The JSON configuration holds the keyring description
125-
* which needs to be converted into the keyring serial number.
126-
*/
127-
if (!strcmp("keyring", key_str) && cfg->keyring == 0) {
128-
long keyring;
129-
130-
keyring_str = json_object_get_string(val_obj);
131-
keyring = nvme_lookup_keyring(keyring_str);
132-
if (keyring) {
133-
cfg->keyring = keyring;
134-
nvme_set_keyring(cfg->keyring);
135-
}
71+
if (!strcmp("keyring", key_str))
72+
nvme_ctrl_set_keyring(c,
73+
json_object_get_string(val_obj));
74+
if (!strcmp("tls_key_identity", key_str)) {
75+
nvme_ctrl_set_tls_key_identity(c,
76+
json_object_get_string(val_obj));
77+
}
78+
if (!strcmp("tls_key", key_str)) {
79+
nvme_ctrl_set_tls_key(c,
80+
json_object_get_string(val_obj));
13681
}
137-
if (!strcmp("tls_key", key_str) && cfg->tls_key == 0)
138-
encoded_key = json_object_get_string(val_obj);
13982
}
140-
141-
/*
142-
* We might need the keyring information from the above loop,
143-
* so we can only import the TLS key once all entries are
144-
* processed.
145-
*/
146-
if (encoded_key)
147-
json_import_nvme_tls_key(c, keyring_str, encoded_key);
14883
}
14984

15085
static void json_parse_port(nvme_subsystem_t s, struct json_object *port_obj)
@@ -181,6 +116,19 @@ static void json_parse_port(nvme_subsystem_t s, struct json_object *port_obj)
181116
attr_obj = json_object_object_get(port_obj, "dhchap_ctrl_key");
182117
if (attr_obj)
183118
nvme_ctrl_set_dhchap_key(c, json_object_get_string(attr_obj));
119+
attr_obj = json_object_object_get(port_obj, "keyring");
120+
if (attr_obj)
121+
nvme_ctrl_set_keyring(c, json_object_get_string(attr_obj));
122+
attr_obj = json_object_object_get(port_obj, "tls_key_identity");
123+
if (attr_obj) {
124+
nvme_ctrl_set_tls_key_identity(c,
125+
json_object_get_string(attr_obj));
126+
}
127+
attr_obj = json_object_object_get(port_obj, "tls_key");
128+
if (attr_obj) {
129+
nvme_ctrl_set_tls_key(c,
130+
json_object_get_string(attr_obj));
131+
}
184132
}
185133

186134
static void json_parse_subsys(nvme_host_t h, struct json_object *subsys_obj)
@@ -368,6 +316,19 @@ static void json_update_port(struct json_object *ctrl_array, nvme_ctrl_t c)
368316
if (value)
369317
json_object_object_add(port_obj, "dhchap_ctrl_key",
370318
json_object_new_string(value));
319+
JSON_BOOL_OPTION(cfg, port_obj, tls);
320+
value = nvme_ctrl_get_keyring(c);
321+
if (value)
322+
json_object_object_add(port_obj, "keyring",
323+
json_object_new_string(value));
324+
value = nvme_ctrl_get_tls_key_identity(c);
325+
if (value)
326+
json_object_object_add(port_obj, "tls_key_identity",
327+
json_object_new_string(value));
328+
value = nvme_ctrl_get_tls_key(c);
329+
if (value)
330+
json_object_object_add(port_obj, "tls_key",
331+
json_object_new_string(value));
371332
JSON_INT_OPTION(cfg, port_obj, nr_io_queues, 0);
372333
JSON_INT_OPTION(cfg, port_obj, nr_write_queues, 0);
373334
JSON_INT_OPTION(cfg, port_obj, nr_poll_queues, 0);
@@ -384,31 +345,13 @@ static void json_update_port(struct json_object *ctrl_array, nvme_ctrl_t c)
384345
JSON_BOOL_OPTION(cfg, port_obj, disable_sqflow);
385346
JSON_BOOL_OPTION(cfg, port_obj, hdr_digest);
386347
JSON_BOOL_OPTION(cfg, port_obj, data_digest);
387-
JSON_BOOL_OPTION(cfg, port_obj, tls);
388348
JSON_BOOL_OPTION(cfg, port_obj, concat);
389349
if (nvme_ctrl_is_persistent(c))
390350
json_object_object_add(port_obj, "persistent",
391351
json_object_new_boolean(true));
392352
if (nvme_ctrl_is_discovery_ctrl(c))
393353
json_object_object_add(port_obj, "discovery",
394354
json_object_new_boolean(true));
395-
/*
396-
* Store the keyring description in the JSON config file.
397-
*/
398-
if (cfg->keyring) {
399-
_cleanup_free_ char *desc =
400-
nvme_describe_key_serial(cfg->keyring);
401-
402-
if (desc) {
403-
json_object_object_add(port_obj, "keyring",
404-
json_object_new_string(desc));
405-
}
406-
}
407-
/*
408-
* Store the TLS key in PSK interchange format
409-
*/
410-
if (cfg->tls_key)
411-
json_export_nvme_tls_key(cfg->keyring, cfg->tls_key, port_obj);
412355

413356
json_object_array_add(ctrl_array, port_obj);
414357
}
@@ -564,9 +507,18 @@ static void json_dump_ctrl(struct json_object *ctrl_array, nvme_ctrl_t c)
564507
if (!strcmp(transport, "tcp")) {
565508
JSON_BOOL_OPTION(cfg, ctrl_obj, tls);
566509

567-
if (cfg->tls_key)
568-
json_export_nvme_tls_key(cfg->keyring, cfg->tls_key,
569-
ctrl_obj);
510+
value = nvme_ctrl_get_keyring(c);
511+
if (value)
512+
json_object_object_add(ctrl_obj, "keyring",
513+
json_object_new_string(value));
514+
value = nvme_ctrl_get_tls_key_identity(c);
515+
if (value)
516+
json_object_object_add(ctrl_obj, "tls_key_identity",
517+
json_object_new_string(value));
518+
value = nvme_ctrl_get_tls_key(c);
519+
if (value)
520+
json_object_object_add(ctrl_obj, "tls_key",
521+
json_object_new_string(value));
570522
}
571523
JSON_BOOL_OPTION(cfg, ctrl_obj, concat);
572524
if (nvme_ctrl_is_persistent(c))

src/nvme/linux.c

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,27 +1347,17 @@ int nvme_scan_tls_keys(const char *keyring, nvme_scan_tls_keys_cb_t cb,
13471347
return ret;
13481348
}
13491349

1350-
long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type,
1351-
const char *hostnqn, const char *subsysnqn,
1352-
int version, int hmac,
1353-
unsigned char *configured_key, int key_len)
1350+
static long __nvme_insert_tls_key_versioned(key_serial_t keyring_id, const char *key_type,
1351+
const char *hostnqn, const char *subsysnqn,
1352+
int version, int hmac,
1353+
unsigned char *configured_key, int key_len)
13541354
{
13551355
_cleanup_free_ unsigned char *psk = NULL;
13561356
_cleanup_free_ char *identity = NULL;
1357-
key_serial_t keyring_id, key;
13581357
ssize_t identity_len;
1358+
key_serial_t key;
13591359
int ret;
13601360

1361-
keyring_id = nvme_lookup_keyring(keyring);
1362-
if (keyring_id == 0) {
1363-
errno = ENOKEY;
1364-
return 0;
1365-
}
1366-
1367-
ret = nvme_set_keyring(keyring_id);
1368-
if (ret < 0)
1369-
return 0;
1370-
13711361
identity_len = nvme_identity_len(hmac, version, hostnqn, subsysnqn);
13721362
if (identity_len < 0)
13731363
return 0;
@@ -1397,6 +1387,29 @@ long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type,
13971387
return key;
13981388
}
13991389

1390+
long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type,
1391+
const char *hostnqn, const char *subsysnqn,
1392+
int version, int hmac,
1393+
unsigned char *configured_key, int key_len)
1394+
{
1395+
key_serial_t keyring_id;
1396+
int ret;
1397+
1398+
keyring_id = nvme_lookup_keyring(keyring);
1399+
if (keyring_id == 0) {
1400+
errno = ENOKEY;
1401+
return 0;
1402+
}
1403+
1404+
ret = nvme_set_keyring(keyring_id);
1405+
if (ret < 0)
1406+
return 0;
1407+
return __nvme_insert_tls_key_versioned(keyring_id, key_type,
1408+
hostnqn, subsysnqn,
1409+
version, hmac,
1410+
configured_key, key_len);
1411+
}
1412+
14001413
long nvme_revoke_tls_key(const char *keyring, const char *key_type,
14011414
const char *identity)
14021415
{
@@ -1415,6 +1428,59 @@ long nvme_revoke_tls_key(const char *keyring, const char *key_type,
14151428

14161429
return keyctl_revoke(key);
14171430
}
1431+
1432+
int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c,
1433+
long *keyring_id, long *key_id)
1434+
{
1435+
const char *hostnqn = nvme_host_get_hostnqn(h);
1436+
const char *subsysnqn = nvme_ctrl_get_subsysnqn(c);
1437+
const char *keyring, *key;
1438+
_cleanup_free_ unsigned char *key_data = NULL;
1439+
unsigned char version;
1440+
unsigned char hmac;
1441+
size_t key_len;
1442+
long id;
1443+
1444+
if (!hostnqn || !subsysnqn) {
1445+
nvme_msg(h->r, LOG_ERR, "Invalid NQNs (%s, %s)\n",
1446+
hostnqn, subsysnqn);
1447+
return -EINVAL;
1448+
}
1449+
1450+
keyring = nvme_ctrl_get_keyring(c);
1451+
if (keyring)
1452+
id = nvme_lookup_keyring(keyring);
1453+
else
1454+
id = c->cfg.keyring;
1455+
1456+
if (nvme_set_keyring(id) < 0) {
1457+
nvme_msg(h->r, LOG_ERR, "Failed to set keyring\n");
1458+
return -errno;
1459+
}
1460+
*keyring_id = id;
1461+
1462+
key = nvme_ctrl_get_tls_key(c);
1463+
key_data = nvme_import_tls_key_versioned(key, &version,
1464+
&hmac, &key_len);
1465+
if (!key_data) {
1466+
nvme_msg(h->r, LOG_ERR, "Failed to decode TLS Key '%s'\n",
1467+
key);
1468+
return -1;
1469+
}
1470+
1471+
id = __nvme_insert_tls_key_versioned(*keyring_id, "psk",
1472+
hostnqn, subsysnqn,
1473+
version, hmac, key_data, key_len);
1474+
if (id <= 0) {
1475+
nvme_msg(h->r, LOG_ERR, "Failed to insert TLS KEY, error %d\n",
1476+
errno);
1477+
return -errno;
1478+
}
1479+
1480+
*key_id = id;
1481+
1482+
return 0;
1483+
}
14181484
#else
14191485
long nvme_lookup_keyring(const char *keyring)
14201486
{
@@ -1488,6 +1554,14 @@ long nvme_revoke_tls_key(const char *keyring, const char *key_type,
14881554
errno = ENOTSUP;
14891555
return -1;
14901556
}
1557+
1558+
int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c,
1559+
long *keyring_id, long *key_id)
1560+
{
1561+
nvme_msg(h->r, LOG_ERR, "key operations not supported; "
1562+
"recompile with keyutils support.\n");
1563+
return -ENOTSUP;
1564+
}
14911565
#endif
14921566

14931567
long nvme_insert_tls_key(const char *keyring, const char *key_type,

0 commit comments

Comments
 (0)