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