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