xref: /spdk/module/keyring/file/keyring.c (revision 91fcde065a5883d85ca1034a9a1b254e1eadbcad)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2024 Intel Corporation. All rights reserved.
3  */
4 
5 #include "keyring_file.h"
6 #include "spdk/keyring_module.h"
7 #include "spdk/log.h"
8 #include "spdk/string.h"
9 #include "spdk/util.h"
10 
11 struct keyring_file_key {
12 	char *path;
13 };
14 
15 static int
16 keyring_file_check_path(const char *path, int *size)
17 {
18 	struct stat st;
19 	int rc, errsv;
20 
21 	if (path[0] != '/') {
22 		SPDK_ERRLOG("Non-absolute paths are not allowed: %s\n", path);
23 		return -EPERM;
24 	}
25 
26 	rc = stat(path, &st);
27 	if (rc != 0) {
28 		errsv = errno;
29 		SPDK_ERRLOG("Could not stat key file '%s': %s\n", path, spdk_strerror(errsv));
30 		return -errsv;
31 	}
32 
33 	if ((st.st_mode & 077) || st.st_uid != getuid()) {
34 		SPDK_ERRLOG("Invalid permissions for key file '%s': 0%o\n", path, st.st_mode);
35 		return -EPERM;
36 	}
37 
38 	if (size != NULL) {
39 		*size = st.st_size;
40 	}
41 
42 	return 0;
43 }
44 
45 static void
46 keyring_file_write_key_config(void *ctx, struct spdk_key *key)
47 {
48 	struct spdk_json_write_ctx *w = ctx;
49 	struct keyring_file_key *kkey;
50 
51 	if (spdk_key_get_module(key) != &g_keyring_file) {
52 		return;
53 	}
54 
55 	kkey = spdk_key_get_ctx(key);
56 
57 	spdk_json_write_object_begin(w);
58 	spdk_json_write_named_string(w, "method", "keyring_file_add_key");
59 	spdk_json_write_named_object_begin(w, "params");
60 	spdk_json_write_named_string(w, "name", spdk_key_get_name(key));
61 	spdk_json_write_named_string(w, "path", kkey->path);
62 	spdk_json_write_object_end(w);
63 	spdk_json_write_object_end(w);
64 }
65 
66 static void
67 keyring_file_write_config(struct spdk_json_write_ctx *w)
68 {
69 	spdk_keyring_for_each_key(NULL, w, keyring_file_write_key_config, 0);
70 }
71 
72 static void
73 keyring_file_dump_info(struct spdk_key *key, struct spdk_json_write_ctx *w)
74 {
75 	struct keyring_file_key *kkey = spdk_key_get_ctx(key);
76 
77 	spdk_json_write_named_string(w, "path", kkey->path);
78 }
79 
80 static size_t
81 keyring_file_get_ctx_size(void)
82 {
83 	return sizeof(struct keyring_file_key);
84 }
85 
86 static int
87 keyring_file_get_key(struct spdk_key *key, void *buf, int len)
88 {
89 	struct keyring_file_key *kkey = spdk_key_get_ctx(key);
90 	FILE *file;
91 	int rc, errsv, size = 0;
92 
93 	rc = keyring_file_check_path(kkey->path, &size);
94 	if (rc != 0) {
95 		return rc;
96 	}
97 
98 	if (size > len) {
99 		SPDK_ERRLOG("Invalid key '%s' size: %d > %d\n", spdk_key_get_name(key), size, len);
100 		return -ENOBUFS;
101 	}
102 
103 	file = fopen(kkey->path, "r");
104 	if (!file) {
105 		errsv = errno;
106 		SPDK_ERRLOG("Could not open key '%s': %s\n", spdk_key_get_name(key),
107 			    spdk_strerror(errsv));
108 		return -errsv;
109 	}
110 
111 	rc = (int)fread(buf, 1, size, file);
112 	if (rc != size) {
113 		SPDK_ERRLOG("Could not load key '%s'\n", spdk_key_get_name(key));
114 		rc = -EIO;
115 	}
116 
117 	fclose(file);
118 
119 	return rc;
120 }
121 
122 static void
123 keyring_file_remove_key(struct spdk_key *key)
124 {
125 	struct keyring_file_key *kkey = spdk_key_get_ctx(key);
126 
127 	free(kkey->path);
128 }
129 
130 static int
131 keyring_file_add_key(struct spdk_key *key, void *ctx)
132 {
133 	struct keyring_file_key_opts *opts = ctx;
134 	struct keyring_file_key *kkey = spdk_key_get_ctx(key);
135 	int rc;
136 
137 	rc = keyring_file_check_path(opts->path, NULL);
138 	if (rc != 0) {
139 		return rc;
140 	}
141 
142 	kkey->path = strdup(opts->path);
143 	if (kkey->path == NULL) {
144 		return -ENOMEM;
145 	}
146 
147 	return 0;
148 }
149 
150 struct spdk_keyring_module g_keyring_file = {
151 	.name = "keyring_file",
152 	.add_key = keyring_file_add_key,
153 	.remove_key = keyring_file_remove_key,
154 	.get_key = keyring_file_get_key,
155 	.get_ctx_size = keyring_file_get_ctx_size,
156 	.dump_info = keyring_file_dump_info,
157 	.write_config = keyring_file_write_config,
158 };
159 
160 SPDK_KEYRING_REGISTER_MODULE(keyring_file, &g_keyring_file);
161