Update Debian Vcs-* fields to point to git repository
[onak.git] / keydb_db2.c
1 /*
2  * keydb_db2.c - Routines to store and fetch keys in a DB2 file (a la pksd)
3  *
4  * Copyright 2002-2004 Jonathan McDowell <noodles@earth.li>
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 <sys/types.h>
21 #include <sys/uio.h>
22 #include <db2/db.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include "charfuncs.h"
31 #include "keydb.h"
32 #include "keyid.h"
33 #include "keyindex.h"
34 #include "keystructs.h"
35 #include "log.h"
36 #include "mem.h"
37 #include "onak-conf.h"
38 #include "parsekey.h"
39
40 #define KEYDB_KEYID_BYTES 4
41
42 /**
43  *      db2_numdb - The number of database files we have.
44  */
45 static int db2_numdb = 16;
46
47 /**
48  *      db2_keydbfiles - An array of DB structs for our key database files.
49  */
50 static DB **db2_keydbfiles = NULL;
51
52 /**
53  *      db2_env - Database environment variable.
54  */
55 static DB_ENV db2_env;
56
57 DB *keydb(DBT *key)
58 {
59         /*
60          * keyid's are 8 bytes, msb first.  so start from the end.  use 16
61          * bits, since that's enough to divide by any small number of db files.
62          */
63         unsigned char *keydata = (unsigned char *) key->data;
64         unsigned long keyidnum;
65
66         keyidnum = (keydata[KEYDB_KEYID_BYTES-2]<<8)|keydata[KEYDB_KEYID_BYTES-1];
67         return(db2_keydbfiles[keyidnum % db2_numdb]);
68 }
69
70 /**
71  *      initdb - Initialize the key database.
72  *
73  *      This function should be called before any of the other functions in
74  *      this file are called in order to allow the DB to be initialized ready
75  *      for access.
76  */
77 void initdb(bool readonly)
78 {
79         DB_INFO keydbinfo;
80         int i;
81         int ret;
82         char keydbname[20];
83         char buf[1024];
84         FILE *numdb = NULL;
85
86         snprintf(buf, sizeof(buf) - 1, "%s/num_keydb", config.db_dir);
87         numdb = fopen(buf, "r");
88         if (numdb != NULL) {
89                 if (fgets(buf, sizeof(buf), numdb) != NULL) {
90                         db2_numdb = atoi(buf);
91                 }
92                 fclose(numdb);
93         } else {
94                 logthing(LOGTHING_ERROR, "Couldn't open num_keydb: %s",
95                                 strerror(errno));
96         }
97
98         memset(&db2_env, 0, sizeof(db2_env));
99
100         /*
101          * Tunable param. Just using what pksd does for the moment. Bigger uses
102          * more memory but improves performance. Bigger than physical memory
103          * makes no sense.
104          */
105         db2_env.mp_size = 20 * 1024 * 1024;
106
107         ret = db_appinit(config.db_dir, NULL,
108                         &db2_env, DB_INIT_MPOOL|DB_INIT_LOCK);
109         if (!ret) {
110                 db2_keydbfiles = (DB **) malloc(sizeof (DB *) * db2_numdb);
111                 memset(&keydbinfo, 0, sizeof(keydbinfo));
112                 keydbinfo.db_pagesize = 8192;
113                 for (i = 0; i < db2_numdb; i++) {
114                         db2_keydbfiles[i] = NULL;
115                         snprintf(keydbname, 19, "keydb%03d", i);
116                         ret = db_open(keydbname, DB_HASH, DB_RDONLY, 0644,
117                                         &db2_env, &keydbinfo,
118                                         &db2_keydbfiles[i]);
119                         if (ret) {
120                                 logthing(LOGTHING_CRITICAL,
121                                         "Error opening db file %d (errno %d)",
122                                         i, ret);
123                                 exit(1);
124                         }
125                 }
126         } else {
127                 logthing(LOGTHING_CRITICAL, "Error initializing db (%d).",
128                                 ret);
129                 exit(1);
130         }
131 }
132
133 /**
134  *      cleanupdb - De-initialize the key database.
135  *
136  *      This function should be called upon program exit to allow the DB to
137  *      cleanup after itself.
138  */
139 void cleanupdb(void)
140 {
141         int i;
142
143         for (i = 0; i < db2_numdb; i++) {
144                 if (db2_keydbfiles[i] != NULL) {
145                         (*(db2_keydbfiles[i]->close))(db2_keydbfiles[i], 0);
146                         db2_keydbfiles[i] = NULL;
147                 }
148         }
149
150         db_appexit(&db2_env);
151 }
152
153 /**
154  *      starttrans - Start a transaction.
155  *
156  *      Start a transaction. Intended to be used if we're about to perform many
157  *      operations on the database to help speed it all up, or if we want
158  *      something to only succeed if all relevant operations are successful.
159  */
160 bool starttrans(void)
161 {
162         return true;
163 }
164
165 /**
166  *      endtrans - End a transaction.
167  *
168  *      Ends a transaction.
169  */
170 void endtrans(void)
171 {
172         return;
173 }
174
175 /**
176  *      fetch_key - Given a keyid fetch the key from storage.
177  *      @keyid: The keyid to fetch.
178  *      @publickey: A pointer to a structure to return the key in.
179  *      @intrans: If we're already in a transaction.
180  *
181  *      We use the hex representation of the keyid as the filename to fetch the
182  *      key from. The key is stored in the file as a binary OpenPGP stream of
183  *      packets, so we can just use read_openpgp_stream() to read the packets
184  *      in and then parse_keys() to parse the packets into a publickey
185  *      structure.
186  */
187 int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
188                 bool intrans)
189 {
190         struct openpgp_packet_list *packets = NULL;
191         int ret;
192         DBT key, data;
193         char id[KEYDB_KEYID_BYTES];
194         struct buffer_ctx fetchbuf;
195
196         memset(&key, 0, sizeof(key));
197         memset(&data, 0, sizeof(data));
198
199         id[0] = (keyid >> 24) & 0xFF;
200         id[1] = (keyid >> 16) & 0xFF;
201         id[2] = (keyid >> 8) & 0xFF;
202         id[3] = keyid & 0xFF;
203
204         key.data = id;
205         key.size = KEYDB_KEYID_BYTES;
206
207         ret = (*(keydb(&key)->get))(keydb(&key), NULL, &key, &data, 0);
208         if (ret == 0) {
209                 fetchbuf.buffer = data.data;
210                 fetchbuf.offset = 0;
211                 fetchbuf.size = data.size;
212                 read_openpgp_stream(buffer_fetchchar, &fetchbuf, &packets, 0);
213                 parse_keys(packets, publickey);
214                 free_packet_list(packets);
215                 packets = NULL;
216         }
217
218         return (!ret);
219 }
220
221 /**
222  *      fetch_key_text - Trys to find the keys that contain the supplied text.
223  *      @search: The text to search for.
224  *      @publickey: A pointer to a structure to return the key in.
225  *
226  *      This function searches for the supplied text and returns the keys that
227  *      contain it.
228  */
229 int fetch_key_text(const char *search, struct openpgp_publickey **publickey)
230 {
231         return 0;
232 }
233
234 /**
235  *      store_key - Takes a key and stores it.
236  *      @publickey: A pointer to the public key to store.
237  *      @intrans: If we're already in a transaction.
238  *      @update: If true the key exists and should be updated.
239  *
240  *      Again we just use the hex representation of the keyid as the filename
241  *      to store the key to. We flatten the public key to a list of OpenPGP
242  *      packets and then use write_openpgp_stream() to write the stream out to
243  *      the file.
244  */
245 int store_key(struct openpgp_publickey *publickey, bool intrans, bool update)
246 {
247         return 0;
248 }
249
250 /**
251  *      delete_key - Given a keyid delete the key from storage.
252  *      @keyid: The keyid to delete.
253  *      @intrans: If we're already in a transaction.
254  *
255  *      This function deletes a public key from whatever storage mechanism we
256  *      are using. Returns 0 if the key existed.
257  */
258 int delete_key(uint64_t keyid, bool intrans)
259 {
260         return (1);
261 }
262
263 /**
264  *      iterate_keys - call a function once for each key in the db.
265  *      @iterfunc: The function to call.
266  *      @ctx: A context pointer
267  *
268  *      Calls iterfunc once for each key in the database. ctx is passed
269  *      unaltered to iterfunc. This function is intended to aid database dumps
270  *      and statistic calculations.
271  *
272  *      Returns the number of keys we iterated over.
273  */
274 int iterate_keys(void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
275                 void *ctx)
276 {
277         return 0;
278 }
279
280 /*
281  * Include the basic keydb routines.
282  */
283 #define NEED_KEYID2UID 1
284 #define NEED_GETKEYSIGS 1
285 #define NEED_GETFULLKEYID 1
286 #define NEED_UPDATEKEYS 1
287 #include "keydb.c"