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