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