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