cscvs to tla changeset 1
[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 "parsekey.h"
25
26 #define DBDIR "/community/pgp-keyserver/db-copy"
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(DBDIR, NULL, &db2_env, DB_INIT_MPOOL|DB_INIT_LOCK);
115         if (!ret) {
116                 db2_keydbfiles = (DB **) malloc(sizeof (DB *) * db2_numdb);
117                 memset(&keydbinfo, 0, sizeof(keydbinfo));
118                 keydbinfo.db_pagesize = 8192;
119                 for (i = 0; i < db2_numdb; i++) {
120                         db2_keydbfiles[i] = NULL;
121                         snprintf(keydbname, 19, "keydb%03d", i);
122                         ret = db_open(keydbname, DB_HASH, DB_RDONLY, 0644,
123                                         &db2_env, &keydbinfo,
124                                         &db2_keydbfiles[i]);
125                         if (ret) {
126                                 fprintf(stderr, "Error opening db file %d (errno %d)\n",
127                                         i, ret);
128                                 exit(1);
129                         }
130                 }
131         } else {
132                 fprintf(stderr, "Error initializing db (%d).\n", ret);
133                 exit(1);
134         }
135 }
136
137 /**
138  *      cleanupdb - De-initialize the key database.
139  *
140  *      This function should be called upon program exit to allow the DB to
141  *      cleanup after itself.
142  */
143 void cleanupdb(void)
144 {
145         int i;
146
147         for (i = 0; i < db2_numdb; i++) {
148                 if (db2_keydbfiles[i] != NULL) {
149                         (*(db2_keydbfiles[i]->close))(db2_keydbfiles[i], 0);
150                         db2_keydbfiles[i] = NULL;
151                 }
152         }
153
154         db_appexit(&db2_env);
155 }
156
157 /**
158  *      fetch_key - Given a keyid fetch the key from storage.
159  *      @keyid: The keyid to fetch.
160  *      @publickey: A pointer to a structure to return the key in.
161  *
162  *      We use the hex representation of the keyid as the filename to fetch the
163  *      key from. The key is stored in the file as a binary OpenPGP stream of
164  *      packets, so we can just use read_openpgp_stream() to read the packets
165  *      in and then parse_keys() to parse the packets into a publickey
166  *      structure.
167  */
168 int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey)
169 {
170         struct openpgp_packet_list *packets = NULL;
171         int ret;
172         DBT key, data;
173         char id[KEYDB_KEYID_BYTES];
174         struct db2_get_ctx fetchbuf;
175
176         memset(&key, 0, sizeof(key));
177         memset(&data, 0, sizeof(data));
178
179         id[0] = (keyid >> 24) & 0xFF;
180         id[1] = (keyid >> 16) & 0xFF;
181         id[2] = (keyid >> 8) & 0xFF;
182         id[3] = keyid & 0xFF;
183
184         key.data = id;
185         key.size = KEYDB_KEYID_BYTES;
186
187         ret = (*(keydb(&key)->get))(keydb(&key), NULL, &key, &data, 0);
188         if (ret == 0) {
189                 //do stuff with data.
190                 fetchbuf.buffer = data.data;
191                 fetchbuf.offset = 0;
192                 fetchbuf.size = data.size;
193                 read_openpgp_stream(keydb_fetchchar, &fetchbuf, &packets);
194                 parse_keys(packets, publickey);
195         }
196
197         return (!ret);
198 }
199
200 /**
201  *      store_key - Takes a key and stores it.
202  *      @publickey: A pointer to the public key to store.
203  *
204  *      Again we just use the hex representation of the keyid as the filename
205  *      to store the key to. We flatten the public key to a list of OpenPGP
206  *      packets and then use write_openpgp_stream() to write the stream out to
207  *      the file.
208  */
209 int store_key(struct openpgp_publickey *publickey)
210 {
211         return 0;
212 }
213
214 /**
215  *      delete_key - Given a keyid delete the key from storage.
216  *      @keyid: The keyid to delete.
217  *
218  *      This function deletes a public key from whatever storage mechanism we
219  *      are using. Returns 0 if the key existed.
220  */
221 int delete_key(uint64_t keyid)
222 {
223         return (1);
224 }
225
226 /*
227  * Include the basic keydb routines.
228  */
229 #include "keydb.c"