cscvs to tla changeset 2
[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  *      fetch_key - Given a keyid fetch the key from storage.
160  *      @keyid: The keyid to fetch.
161  *      @publickey: A pointer to a structure to return the key in.
162  *
163  *      We use the hex representation of the keyid as the filename to fetch the
164  *      key from. The key is stored in the file as a binary OpenPGP stream of
165  *      packets, so we can just use read_openpgp_stream() to read the packets
166  *      in and then parse_keys() to parse the packets into a publickey
167  *      structure.
168  */
169 int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey)
170 {
171         struct openpgp_packet_list *packets = NULL;
172         int ret;
173         DBT key, data;
174         char id[KEYDB_KEYID_BYTES];
175         struct db2_get_ctx fetchbuf;
176
177         memset(&key, 0, sizeof(key));
178         memset(&data, 0, sizeof(data));
179
180         id[0] = (keyid >> 24) & 0xFF;
181         id[1] = (keyid >> 16) & 0xFF;
182         id[2] = (keyid >> 8) & 0xFF;
183         id[3] = keyid & 0xFF;
184
185         key.data = id;
186         key.size = KEYDB_KEYID_BYTES;
187
188         ret = (*(keydb(&key)->get))(keydb(&key), NULL, &key, &data, 0);
189         if (ret == 0) {
190                 //do stuff with data.
191                 fetchbuf.buffer = data.data;
192                 fetchbuf.offset = 0;
193                 fetchbuf.size = data.size;
194                 read_openpgp_stream(keydb_fetchchar, &fetchbuf, &packets);
195                 parse_keys(packets, publickey);
196         }
197
198         return (!ret);
199 }
200
201 /**
202  *      store_key - Takes a key and stores it.
203  *      @publickey: A pointer to the public key to store.
204  *
205  *      Again we just use the hex representation of the keyid as the filename
206  *      to store the key to. We flatten the public key to a list of OpenPGP
207  *      packets and then use write_openpgp_stream() to write the stream out to
208  *      the file.
209  */
210 int store_key(struct openpgp_publickey *publickey)
211 {
212         return 0;
213 }
214
215 /**
216  *      delete_key - Given a keyid delete the key from storage.
217  *      @keyid: The keyid to delete.
218  *
219  *      This function deletes a public key from whatever storage mechanism we
220  *      are using. Returns 0 if the key existed.
221  */
222 int delete_key(uint64_t keyid)
223 {
224         return (1);
225 }
226
227 /*
228  * Include the basic keydb routines.
229  */
230 #define NEED_KEYID2UID 1
231 #define NEED_GETKEYSIGS 1
232 #include "keydb.c"