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