]> the.earth.li Git - onak.git/blob - keydb/keydb_dynamic.c
Provide key_fetch routine that will not search subkey fingerprints
[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(struct onak_dbctx *dbctx,
58                 struct openpgp_fingerprint *fingerprint,
59                 struct openpgp_publickey **publickey, bool intrans)
60 {
61         struct onak_dynamic_dbctx *privctx =
62                         (struct onak_dynamic_dbctx *) dbctx->priv;
63
64         return privctx->loadeddbctx->fetch_key(privctx->loadeddbctx,
65                         fingerprint, publickey, intrans);
66 }
67
68 static int dynamic_fetch_key_fp(struct onak_dbctx *dbctx,
69                 struct openpgp_fingerprint *fingerprint,
70                 struct openpgp_publickey **publickey, bool intrans)
71 {
72         struct onak_dynamic_dbctx *privctx =
73                         (struct onak_dynamic_dbctx *) dbctx->priv;
74
75         if (privctx->loadeddbctx->fetch_key_fp)
76                 return privctx->loadeddbctx->fetch_key_fp(privctx->loadeddbctx,
77                         fingerprint, publickey, intrans);
78         else
79                 return privctx->loadeddbctx->fetch_key(privctx->loadeddbctx,
80                         fingerprint, publickey, intrans);
81 }
82
83 static int dynamic_fetch_key_id(struct onak_dbctx *dbctx, uint64_t keyid,
84                 struct openpgp_publickey **publickey, bool intrans)
85 {
86         struct onak_dynamic_dbctx *privctx =
87                         (struct onak_dynamic_dbctx *) dbctx->priv;
88
89         return privctx->loadeddbctx->fetch_key_id(privctx->loadeddbctx, keyid,
90                         publickey, intrans);
91 }
92
93 static int dynamic_fetch_key_text(struct onak_dbctx *dbctx,
94                 const char *search,
95                 struct openpgp_publickey **publickey)
96 {
97         struct onak_dynamic_dbctx *privctx =
98                         (struct onak_dynamic_dbctx *) dbctx->priv;
99
100         return privctx->loadeddbctx->fetch_key_text(privctx->loadeddbctx,
101                         search, publickey);
102 }
103
104 static int dynamic_fetch_key_skshash(struct onak_dbctx *dbctx,
105                 const struct skshash *hash,
106                 struct openpgp_publickey **publickey)
107 {
108         struct onak_dynamic_dbctx *privctx =
109                         (struct onak_dynamic_dbctx *) dbctx->priv;
110
111         return privctx->loadeddbctx->fetch_key_skshash(privctx->loadeddbctx,
112                         hash, publickey);
113 }
114
115 static int dynamic_store_key(struct onak_dbctx *dbctx,
116                 struct openpgp_publickey *publickey, bool intrans,
117                 bool update)
118 {
119         struct onak_dynamic_dbctx *privctx =
120                         (struct onak_dynamic_dbctx *) dbctx->priv;
121
122         return privctx->loadeddbctx->store_key(privctx->loadeddbctx,
123                         publickey, intrans, update);
124 }
125
126 static int dynamic_delete_key(struct onak_dbctx *dbctx,
127                 struct openpgp_fingerprint *fp,
128                 bool intrans)
129 {
130         struct onak_dynamic_dbctx *privctx =
131                         (struct onak_dynamic_dbctx *) dbctx->priv;
132
133         return privctx->loadeddbctx->delete_key(privctx->loadeddbctx,
134                         fp, intrans);
135 }
136
137 static int dynamic_update_keys(struct onak_dbctx *dbctx,
138                 struct openpgp_publickey **keys,
139                 struct keyarray *blacklist,
140                 bool updateonly,
141                 bool sendsync)
142 {
143         struct onak_dynamic_dbctx *privctx =
144                         (struct onak_dynamic_dbctx *) dbctx->priv;
145
146         return privctx->loadeddbctx->update_keys(privctx->loadeddbctx,
147                         keys, blacklist, updateonly, sendsync);
148 }
149
150 static struct ll *dynamic_getkeysigs(struct onak_dbctx *dbctx,
151                 uint64_t keyid, bool *revoked)
152 {
153         struct onak_dynamic_dbctx *privctx =
154                         (struct onak_dynamic_dbctx *) dbctx->priv;
155
156         return privctx->loadeddbctx->getkeysigs(privctx->loadeddbctx,
157                         keyid, revoked);
158 }
159
160 static struct ll *dynamic_cached_getkeysigs(struct onak_dbctx *dbctx,
161                 uint64_t keyid)
162 {
163         struct onak_dynamic_dbctx *privctx =
164                         (struct onak_dynamic_dbctx *) dbctx->priv;
165
166         return privctx->loadeddbctx->cached_getkeysigs(privctx->loadeddbctx,
167                         keyid);
168 }
169
170 static char *dynamic_keyid2uid(struct onak_dbctx *dbctx,
171                         uint64_t keyid)
172 {
173         struct onak_dynamic_dbctx *privctx =
174                         (struct onak_dynamic_dbctx *) dbctx->priv;
175
176         return privctx->loadeddbctx->keyid2uid(privctx->loadeddbctx,
177                         keyid);
178 }
179
180 static int dynamic_iterate_keys(struct onak_dbctx *dbctx,
181                 void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
182                 void *ctx)
183 {
184         struct onak_dynamic_dbctx *privctx =
185                         (struct onak_dynamic_dbctx *) dbctx->priv;
186
187         return privctx->loadeddbctx->iterate_keys(privctx->loadeddbctx,
188                         iterfunc, ctx);
189 }
190
191 static void dynamic_cleanupdb(struct onak_dbctx *dbctx)
192 {
193         struct onak_dynamic_dbctx *privctx =
194                         (struct onak_dynamic_dbctx *) dbctx->priv;
195
196         if (privctx->loadeddbctx != NULL) {
197                 if (privctx->loadeddbctx->cleanupdb != NULL) {
198                         privctx->loadeddbctx->cleanupdb(privctx->loadeddbctx);
199                         privctx->loadeddbctx = NULL;
200                 }
201         }
202
203         if (privctx->backend_handle != NULL) {
204                 dlclose(privctx->backend_handle);
205                 privctx->backend_handle = NULL;
206         }
207
208         if (dbctx->priv != NULL) {
209                 free(dbctx->priv);
210                 dbctx->priv = NULL;
211         }
212
213         if (dbctx != NULL) {
214                 free(dbctx);
215         }
216 }
217
218 struct onak_dbctx *keydb_dynamic_init(struct onak_db_config *dbcfg,
219                 bool readonly)
220 {
221         struct onak_dbctx *dbctx;
222         char *soname;
223         char *initname;
224         struct onak_dbctx *(*backend_init)(struct onak_db_config *, bool);
225         struct onak_dynamic_dbctx *privctx;
226         char *type;
227
228         if (dbcfg == NULL) {
229                 logthing(LOGTHING_CRITICAL,
230                         "No backend database configuration supplied.");
231                 return NULL;
232         }
233
234         dbctx = malloc(sizeof(struct onak_dbctx));
235
236         if (dbctx == NULL) {
237                 return NULL;
238         }
239
240         dbctx->config = dbcfg;
241         dbctx->priv = privctx = malloc(sizeof(struct onak_dynamic_dbctx));
242         if (dbctx->priv == NULL) {
243                 free(dbctx);
244                 return (NULL);
245         }
246
247         type = dbcfg->type;
248         if (config.use_keyd) {
249                 type = "keyd";
250         }
251
252         if (!config.db_backend) {
253                 logthing(LOGTHING_CRITICAL, "No database backend defined.");
254                 exit(EXIT_FAILURE);
255         }
256
257         if (config.backends_dir == NULL) {
258                 soname = malloc(strlen(type)
259                         + strlen("./libkeydb_")
260                         + strlen(".so")
261                         + 1);
262
263                 sprintf(soname, "./libkeydb_%s.so", type);
264         } else {
265                 soname = malloc(strlen(type)
266                         + strlen("/libkeydb_")
267                         + strlen(".so")
268                         + strlen(config.backends_dir)
269                         + 1);
270
271                 sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir,
272                         type);
273         }
274
275         logthing(LOGTHING_INFO, "Loading dynamic backend: %s", soname);
276
277         privctx->backend_handle = dlopen(soname, RTLD_LAZY);
278         if (privctx->backend_handle == NULL) {
279                 logthing(LOGTHING_CRITICAL,
280                                 "Failed to open handle to library '%s': %s",
281                                 soname, dlerror());
282                 free(soname);
283                 soname = NULL;
284                 exit(EXIT_FAILURE);
285         }
286
287         initname = malloc(strlen(config.db_backend)
288                         + strlen("keydb_")
289                         + strlen("_init")
290                         + 1);
291         sprintf(initname, "keydb_%s_init", type);
292
293         *(void **) (&backend_init) = dlsym(privctx->backend_handle, initname);
294         free(initname);
295
296         if (backend_init == NULL) {
297                 logthing(LOGTHING_CRITICAL,
298                                 "Failed to find dbfuncs structure in library "
299                                 "'%s' : %s", soname, dlerror());
300                 free(soname);
301                 soname = NULL;
302                 exit(EXIT_FAILURE);
303         }
304
305         privctx->loadeddbctx = backend_init(dbcfg, readonly);
306
307         if (privctx->loadeddbctx == NULL) {
308                 logthing(LOGTHING_CRITICAL,
309                                 "Failed to initialise dynamic backend: %s",
310                                 soname);
311                 free(soname);
312                 soname = NULL;
313                 exit(EXIT_FAILURE);
314         }
315         free(soname);
316         soname = NULL;
317
318         if (privctx->loadeddbctx != NULL) {
319                 dbctx->cleanupdb = dynamic_cleanupdb;
320                 dbctx->starttrans = dynamic_starttrans;
321                 dbctx->endtrans = dynamic_endtrans;
322                 dbctx->fetch_key = dynamic_fetch_key;
323                 dbctx->fetch_key_fp = dynamic_fetch_key_fp;
324                 dbctx->fetch_key_id = dynamic_fetch_key_id;
325                 dbctx->fetch_key_text = dynamic_fetch_key_text;
326                 dbctx->fetch_key_skshash = dynamic_fetch_key_skshash;
327                 dbctx->store_key = dynamic_store_key;
328                 dbctx->update_keys = dynamic_update_keys;
329                 dbctx->delete_key = dynamic_delete_key;
330                 dbctx->getkeysigs = dynamic_getkeysigs;
331                 dbctx->cached_getkeysigs = dynamic_cached_getkeysigs;
332                 dbctx->keyid2uid = dynamic_keyid2uid;
333                 dbctx->iterate_keys = dynamic_iterate_keys;
334         }
335
336         return dbctx;
337 }