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