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