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