]> the.earth.li Git - onak.git/blob - keydb_dynamic.c
Use dynamic context for all backend databases
[onak.git] / 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, write to the Free Software Foundation, Inc., 51
17  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <dlfcn.h>
21 #include <stdio.h>
22 #include <string.h>
23
24 #include "decodekey.h"
25 #include "hash.h"
26 #include "keydb.h"
27 #include "keyid.h"
28 #include "keystructs.h"
29 #include "log.h"
30 #include "mem.h"
31 #include "merge.h"
32 #include "onak-conf.h"
33 #include "openpgp.h"
34 #include "parsekey.h"
35 #include "sendsync.h"
36
37 struct onak_dynamic_dbctx {
38         struct onak_dbctx *loadeddbctx;
39         void              *backend_handle;
40 };
41
42 static bool dynamic_starttrans(struct onak_dbctx *dbctx)
43 {
44         struct onak_dynamic_dbctx *privctx =
45                         (struct onak_dynamic_dbctx *) dbctx->priv;
46
47         return privctx->loadeddbctx->starttrans(privctx->loadeddbctx);
48 }
49
50 static void dynamic_endtrans(struct onak_dbctx *dbctx)
51 {
52         struct onak_dynamic_dbctx *privctx =
53                         (struct onak_dynamic_dbctx *) dbctx->priv;
54
55         privctx->loadeddbctx->endtrans(privctx->loadeddbctx);
56 }
57
58 static int dynamic_fetch_key_id(struct onak_dbctx *dbctx, uint64_t keyid,
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_id(privctx->loadeddbctx, keyid,
65                         publickey, intrans);
66 }
67
68 static int dynamic_fetch_key_fp(struct onak_dbctx *dbctx,
69                 uint8_t *fp, size_t fpsize,
70                 struct openpgp_publickey **publickey, bool intrans)
71 {
72         struct onak_dynamic_dbctx *privctx =
73                         (struct onak_dynamic_dbctx *) dbctx->priv;
74
75         return privctx->loadeddbctx->fetch_key_fp(privctx->loadeddbctx,
76                         fp, fpsize, publickey, intrans);
77 }
78
79 static int dynamic_fetch_key_text(struct onak_dbctx *dbctx,
80                 const char *search,
81                 struct openpgp_publickey **publickey)
82 {
83         struct onak_dynamic_dbctx *privctx =
84                         (struct onak_dynamic_dbctx *) dbctx->priv;
85
86         return privctx->loadeddbctx->fetch_key_text(privctx->loadeddbctx,
87                         search, publickey);
88 }
89
90 static int dynamic_fetch_key_skshash(struct onak_dbctx *dbctx,
91                 const struct skshash *hash,
92                 struct openpgp_publickey **publickey)
93 {
94         struct onak_dynamic_dbctx *privctx =
95                         (struct onak_dynamic_dbctx *) dbctx->priv;
96
97         return privctx->loadeddbctx->fetch_key_skshash(privctx->loadeddbctx,
98                         hash, publickey);
99 }
100
101 static int dynamic_store_key(struct onak_dbctx *dbctx,
102                 struct openpgp_publickey *publickey, bool intrans,
103                 bool update)
104 {
105         struct onak_dynamic_dbctx *privctx =
106                         (struct onak_dynamic_dbctx *) dbctx->priv;
107
108         return privctx->loadeddbctx->store_key(privctx->loadeddbctx,
109                         publickey, intrans, update);
110 }
111
112 static int dynamic_delete_key(struct onak_dbctx *dbctx, uint64_t keyid,
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                         keyid, intrans);
120 }
121
122 static int dynamic_update_keys(struct onak_dbctx *dbctx,
123                 struct openpgp_publickey **keys, bool sendsync)
124 {
125         struct onak_dynamic_dbctx *privctx =
126                         (struct onak_dynamic_dbctx *) dbctx->priv;
127
128         return privctx->loadeddbctx->update_keys(privctx->loadeddbctx,
129                         keys, sendsync);
130 }
131
132 static struct ll *dynamic_getkeysigs(struct onak_dbctx *dbctx,
133                 uint64_t keyid, bool *revoked)
134 {
135         struct onak_dynamic_dbctx *privctx =
136                         (struct onak_dynamic_dbctx *) dbctx->priv;
137
138         return privctx->loadeddbctx->getkeysigs(privctx->loadeddbctx,
139                         keyid, revoked);
140 }
141
142 static struct ll *dynamic_cached_getkeysigs(struct onak_dbctx *dbctx,
143                 uint64_t keyid)
144 {
145         struct onak_dynamic_dbctx *privctx =
146                         (struct onak_dynamic_dbctx *) dbctx->priv;
147
148         return privctx->loadeddbctx->cached_getkeysigs(privctx->loadeddbctx,
149                         keyid);
150 }
151
152 static char *dynamic_keyid2uid(struct onak_dbctx *dbctx,
153                         uint64_t keyid)
154 {
155         struct onak_dynamic_dbctx *privctx =
156                         (struct onak_dynamic_dbctx *) dbctx->priv;
157
158         return privctx->loadeddbctx->keyid2uid(privctx->loadeddbctx,
159                         keyid);
160 }
161
162 static uint64_t dynamic_getfullkeyid(struct onak_dbctx *dbctx,
163                 uint64_t keyid)
164 {
165         struct onak_dynamic_dbctx *privctx =
166                         (struct onak_dynamic_dbctx *) dbctx->priv;
167
168         return privctx->loadeddbctx->getfullkeyid(privctx->loadeddbctx, keyid);
169 }
170
171 static int dynamic_iterate_keys(struct onak_dbctx *dbctx,
172                 void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
173                 void *ctx)
174 {
175         struct onak_dynamic_dbctx *privctx =
176                         (struct onak_dynamic_dbctx *) dbctx->priv;
177
178         return privctx->loadeddbctx->iterate_keys(privctx->loadeddbctx,
179                         iterfunc, ctx);
180 }
181
182 static void dynamic_cleanupdb(struct onak_dbctx *dbctx)
183 {
184         struct onak_dynamic_dbctx *privctx =
185                         (struct onak_dynamic_dbctx *) dbctx->priv;
186
187         if (privctx->loadeddbctx != NULL) {
188                 if (privctx->loadeddbctx->cleanupdb != NULL) {
189                         privctx->loadeddbctx->cleanupdb(privctx->loadeddbctx);
190                         privctx->loadeddbctx = NULL;
191                 }
192         }
193
194         if (privctx->backend_handle != NULL) {
195                 dlclose(privctx->backend_handle);
196                 privctx->backend_handle = NULL;
197         }
198
199         if (dbctx->priv != NULL) {
200                 free(dbctx->priv);
201                 dbctx->priv = NULL;
202         }
203
204         if (dbctx != NULL) {
205                 free(dbctx);
206         }
207 }
208
209 struct onak_dbctx *keydb_dynamic_init(bool readonly)
210 {
211         struct onak_dbctx *dbctx;
212         char *soname;
213         char *initname;
214         struct onak_dbctx *(*backend_init)(bool);
215         struct onak_dynamic_dbctx *privctx;
216
217         dbctx = malloc(sizeof(struct onak_dbctx));
218
219         if (dbctx == NULL) {
220                 return NULL;
221         }
222
223         dbctx->priv = privctx = malloc(sizeof(struct onak_dynamic_dbctx));
224         if (dbctx->priv == NULL) {
225                 free(dbctx);
226                 return (NULL);
227         }
228
229         if (config.use_keyd) {
230                 free(config.db_backend);
231                 config.db_backend = strdup("keyd");
232         }
233
234         if (!config.db_backend) {
235                 logthing(LOGTHING_CRITICAL, "No database backend defined.");
236                 exit(EXIT_FAILURE);
237         }
238
239         if (config.backends_dir == NULL) {
240                 soname = malloc(strlen(config.db_backend)
241                         + strlen("./libkeydb_")
242                         + strlen(".so")
243                         + 1);
244
245                 sprintf(soname, "./libkeydb_%s.so", config.db_backend);
246         } else {
247                 soname = malloc(strlen(config.db_backend)
248                         + strlen("/libkeydb_")
249                         + strlen(".so")
250                         + strlen(config.backends_dir)
251                         + 1);
252
253                 sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir,
254                         config.db_backend);
255         }
256
257         logthing(LOGTHING_INFO, "Loading dynamic backend: %s", soname);
258
259         privctx->backend_handle = dlopen(soname, RTLD_LAZY);
260         if (privctx->backend_handle == NULL) {
261                 logthing(LOGTHING_CRITICAL,
262                                 "Failed to open handle to library '%s': %s",
263                                 soname, dlerror());
264                 free(soname);
265                 soname = NULL;
266                 exit(EXIT_FAILURE);
267         }
268
269         initname = malloc(strlen(config.db_backend)
270                         + strlen("keydb_")
271                         + strlen("_init")
272                         + 1);
273         sprintf(initname, "keydb_%s_init", config.db_backend);
274
275         *(void **) (&backend_init) = dlsym(privctx->backend_handle, initname);
276         free(initname);
277
278         if (backend_init == NULL) {
279                 logthing(LOGTHING_CRITICAL,
280                                 "Failed to find dbfuncs structure in library "
281                                 "'%s' : %s", soname, dlerror());
282                 free(soname);
283                 soname = NULL;
284                 exit(EXIT_FAILURE);
285         }
286         free(soname);
287         soname = NULL;
288
289         privctx->loadeddbctx = backend_init(readonly);
290
291         if (privctx->loadeddbctx != NULL) {
292                 dbctx->cleanupdb = dynamic_cleanupdb;
293                 dbctx->starttrans = dynamic_starttrans;
294                 dbctx->endtrans = dynamic_endtrans;
295                 dbctx->fetch_key_id = dynamic_fetch_key_id;
296                 dbctx->fetch_key_fp = dynamic_fetch_key_fp;
297                 dbctx->fetch_key_text = dynamic_fetch_key_text;
298                 dbctx->fetch_key_skshash = dynamic_fetch_key_skshash;
299                 dbctx->store_key = dynamic_store_key;
300                 dbctx->update_keys = dynamic_update_keys;
301                 dbctx->delete_key = dynamic_delete_key;
302                 dbctx->getkeysigs = dynamic_getkeysigs;
303                 dbctx->cached_getkeysigs = dynamic_cached_getkeysigs;
304                 dbctx->keyid2uid = dynamic_keyid2uid;
305                 dbctx->getfullkeyid = dynamic_getfullkeyid;
306                 dbctx->iterate_keys = dynamic_iterate_keys;
307         }
308
309         return dbctx;
310 }