]> the.earth.li Git - onak.git/blob - keydb/keydb_dynamic.c
385c09cbb5ef3600e2b9e9a59a79b61d423f4c03
[onak.git] / keydb / keydb_dynamic.c
1 /*
2  * keydb_dynamic.c - backend that can load the other backends
3  *
4  * Copyright 2005 Brett Parker <iDunno@sommitrealweird.co.uk>
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program.  If not, see <https://www.gnu.org/licenses/>.
17  */
18
19 #include <dlfcn.h>
20 #include <stdio.h>
21 #include <string.h>
22
23 #include "decodekey.h"
24 #include "hash.h"
25 #include "keydb.h"
26 #include "keyid.h"
27 #include "keystructs.h"
28 #include "log.h"
29 #include "mem.h"
30 #include "merge.h"
31 #include "onak-conf.h"
32 #include "openpgp.h"
33 #include "parsekey.h"
34 #include "sendsync.h"
35
36 struct onak_dynamic_dbctx {
37         struct onak_dbctx *loadeddbctx;
38         void              *backend_handle;
39 };
40
41 static bool dynamic_starttrans(struct onak_dbctx *dbctx)
42 {
43         struct onak_dynamic_dbctx *privctx =
44                         (struct onak_dynamic_dbctx *) dbctx->priv;
45
46         return privctx->loadeddbctx->starttrans(privctx->loadeddbctx);
47 }
48
49 static void dynamic_endtrans(struct onak_dbctx *dbctx)
50 {
51         struct onak_dynamic_dbctx *privctx =
52                         (struct onak_dynamic_dbctx *) dbctx->priv;
53
54         privctx->loadeddbctx->endtrans(privctx->loadeddbctx);
55 }
56
57 static int dynamic_fetch_key_id(struct onak_dbctx *dbctx, uint64_t keyid,
58                 struct openpgp_publickey **publickey, bool intrans)
59 {
60         struct onak_dynamic_dbctx *privctx =
61                         (struct onak_dynamic_dbctx *) dbctx->priv;
62
63         return privctx->loadeddbctx->fetch_key_id(privctx->loadeddbctx, keyid,
64                         publickey, intrans);
65 }
66
67 static int dynamic_fetch_key_fp(struct onak_dbctx *dbctx,
68                 struct openpgp_fingerprint *fingerprint,
69                 struct openpgp_publickey **publickey, bool intrans)
70 {
71         struct onak_dynamic_dbctx *privctx =
72                         (struct onak_dynamic_dbctx *) dbctx->priv;
73
74         return privctx->loadeddbctx->fetch_key_fp(privctx->loadeddbctx,
75                         fingerprint, publickey, intrans);
76 }
77
78 static int dynamic_fetch_key_text(struct onak_dbctx *dbctx,
79                 const char *search,
80                 struct openpgp_publickey **publickey)
81 {
82         struct onak_dynamic_dbctx *privctx =
83                         (struct onak_dynamic_dbctx *) dbctx->priv;
84
85         return privctx->loadeddbctx->fetch_key_text(privctx->loadeddbctx,
86                         search, publickey);
87 }
88
89 static int dynamic_fetch_key_skshash(struct onak_dbctx *dbctx,
90                 const struct skshash *hash,
91                 struct openpgp_publickey **publickey)
92 {
93         struct onak_dynamic_dbctx *privctx =
94                         (struct onak_dynamic_dbctx *) dbctx->priv;
95
96         return privctx->loadeddbctx->fetch_key_skshash(privctx->loadeddbctx,
97                         hash, publickey);
98 }
99
100 static int dynamic_store_key(struct onak_dbctx *dbctx,
101                 struct openpgp_publickey *publickey, bool intrans,
102                 bool update)
103 {
104         struct onak_dynamic_dbctx *privctx =
105                         (struct onak_dynamic_dbctx *) dbctx->priv;
106
107         return privctx->loadeddbctx->store_key(privctx->loadeddbctx,
108                         publickey, intrans, update);
109 }
110
111 static int dynamic_delete_key(struct onak_dbctx *dbctx,
112                 struct openpgp_fingerprint *fp,
113                 bool intrans)
114 {
115         struct onak_dynamic_dbctx *privctx =
116                         (struct onak_dynamic_dbctx *) dbctx->priv;
117
118         return privctx->loadeddbctx->delete_key(privctx->loadeddbctx,
119                         fp, intrans);
120 }
121
122 static int dynamic_update_keys(struct onak_dbctx *dbctx,
123                 struct openpgp_publickey **keys,
124                 struct keyarray *blacklist,
125                 bool updateonly,
126                 bool sendsync)
127 {
128         struct onak_dynamic_dbctx *privctx =
129                         (struct onak_dynamic_dbctx *) dbctx->priv;
130
131         return privctx->loadeddbctx->update_keys(privctx->loadeddbctx,
132                         keys, blacklist, updateonly, sendsync);
133 }
134
135 static struct ll *dynamic_getkeysigs(struct onak_dbctx *dbctx,
136                 uint64_t keyid, bool *revoked)
137 {
138         struct onak_dynamic_dbctx *privctx =
139                         (struct onak_dynamic_dbctx *) dbctx->priv;
140
141         return privctx->loadeddbctx->getkeysigs(privctx->loadeddbctx,
142                         keyid, revoked);
143 }
144
145 static struct ll *dynamic_cached_getkeysigs(struct onak_dbctx *dbctx,
146                 uint64_t keyid)
147 {
148         struct onak_dynamic_dbctx *privctx =
149                         (struct onak_dynamic_dbctx *) dbctx->priv;
150
151         return privctx->loadeddbctx->cached_getkeysigs(privctx->loadeddbctx,
152                         keyid);
153 }
154
155 static char *dynamic_keyid2uid(struct onak_dbctx *dbctx,
156                         uint64_t keyid)
157 {
158         struct onak_dynamic_dbctx *privctx =
159                         (struct onak_dynamic_dbctx *) dbctx->priv;
160
161         return privctx->loadeddbctx->keyid2uid(privctx->loadeddbctx,
162                         keyid);
163 }
164
165 static int dynamic_iterate_keys(struct onak_dbctx *dbctx,
166                 void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
167                 void *ctx)
168 {
169         struct onak_dynamic_dbctx *privctx =
170                         (struct onak_dynamic_dbctx *) dbctx->priv;
171
172         return privctx->loadeddbctx->iterate_keys(privctx->loadeddbctx,
173                         iterfunc, ctx);
174 }
175
176 static void dynamic_cleanupdb(struct onak_dbctx *dbctx)
177 {
178         struct onak_dynamic_dbctx *privctx =
179                         (struct onak_dynamic_dbctx *) dbctx->priv;
180
181         if (privctx->loadeddbctx != NULL) {
182                 if (privctx->loadeddbctx->cleanupdb != NULL) {
183                         privctx->loadeddbctx->cleanupdb(privctx->loadeddbctx);
184                         privctx->loadeddbctx = NULL;
185                 }
186         }
187
188         if (privctx->backend_handle != NULL) {
189                 dlclose(privctx->backend_handle);
190                 privctx->backend_handle = NULL;
191         }
192
193         if (dbctx->priv != NULL) {
194                 free(dbctx->priv);
195                 dbctx->priv = NULL;
196         }
197
198         if (dbctx != NULL) {
199                 free(dbctx);
200         }
201 }
202
203 struct onak_dbctx *keydb_dynamic_init(struct onak_db_config *dbcfg,
204                 bool readonly)
205 {
206         struct onak_dbctx *dbctx;
207         char *soname;
208         char *initname;
209         struct onak_dbctx *(*backend_init)(struct onak_db_config *, bool);
210         struct onak_dynamic_dbctx *privctx;
211         char *type;
212
213         if (dbcfg == NULL) {
214                 logthing(LOGTHING_CRITICAL,
215                         "No backend database configuration supplied.");
216                 return NULL;
217         }
218
219         dbctx = malloc(sizeof(struct onak_dbctx));
220
221         if (dbctx == NULL) {
222                 return NULL;
223         }
224
225         dbctx->config = dbcfg;
226         dbctx->priv = privctx = malloc(sizeof(struct onak_dynamic_dbctx));
227         if (dbctx->priv == NULL) {
228                 free(dbctx);
229                 return (NULL);
230         }
231
232         type = dbcfg->type;
233         if (config.use_keyd) {
234                 type = "keyd";
235         }
236
237         if (!config.db_backend) {
238                 logthing(LOGTHING_CRITICAL, "No database backend defined.");
239                 exit(EXIT_FAILURE);
240         }
241
242         if (config.backends_dir == NULL) {
243                 soname = malloc(strlen(type)
244                         + strlen("./libkeydb_")
245                         + strlen(".so")
246                         + 1);
247
248                 sprintf(soname, "./libkeydb_%s.so", type);
249         } else {
250                 soname = malloc(strlen(type)
251                         + strlen("/libkeydb_")
252                         + strlen(".so")
253                         + strlen(config.backends_dir)
254                         + 1);
255
256                 sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir,
257                         type);
258         }
259
260         logthing(LOGTHING_INFO, "Loading dynamic backend: %s", soname);
261
262         privctx->backend_handle = dlopen(soname, RTLD_LAZY);
263         if (privctx->backend_handle == NULL) {
264                 logthing(LOGTHING_CRITICAL,
265                                 "Failed to open handle to library '%s': %s",
266                                 soname, dlerror());
267                 free(soname);
268                 soname = NULL;
269                 exit(EXIT_FAILURE);
270         }
271
272         initname = malloc(strlen(config.db_backend)
273                         + strlen("keydb_")
274                         + strlen("_init")
275                         + 1);
276         sprintf(initname, "keydb_%s_init", type);
277
278         *(void **) (&backend_init) = dlsym(privctx->backend_handle, initname);
279         free(initname);
280
281         if (backend_init == NULL) {
282                 logthing(LOGTHING_CRITICAL,
283                                 "Failed to find dbfuncs structure in library "
284                                 "'%s' : %s", soname, dlerror());
285                 free(soname);
286                 soname = NULL;
287                 exit(EXIT_FAILURE);
288         }
289
290         privctx->loadeddbctx = backend_init(dbcfg, readonly);
291
292         if (privctx->loadeddbctx == NULL) {
293                 logthing(LOGTHING_CRITICAL,
294                                 "Failed to initialise dynamic backend: %s",
295                                 soname);
296                 free(soname);
297                 soname = NULL;
298                 exit(EXIT_FAILURE);
299         }
300         free(soname);
301         soname = NULL;
302
303         if (privctx->loadeddbctx != NULL) {
304                 dbctx->cleanupdb = dynamic_cleanupdb;
305                 dbctx->starttrans = dynamic_starttrans;
306                 dbctx->endtrans = dynamic_endtrans;
307                 dbctx->fetch_key_id = dynamic_fetch_key_id;
308                 dbctx->fetch_key_fp = dynamic_fetch_key_fp;
309                 dbctx->fetch_key_text = dynamic_fetch_key_text;
310                 dbctx->fetch_key_skshash = dynamic_fetch_key_skshash;
311                 dbctx->store_key = dynamic_store_key;
312                 dbctx->update_keys = dynamic_update_keys;
313                 dbctx->delete_key = dynamic_delete_key;
314                 dbctx->getkeysigs = dynamic_getkeysigs;
315                 dbctx->cached_getkeysigs = dynamic_cached_getkeysigs;
316                 dbctx->keyid2uid = dynamic_keyid2uid;
317                 dbctx->iterate_keys = dynamic_iterate_keys;
318         }
319
320         return dbctx;
321 }