2 * keydb.h - Routines to store and fetch keys.
4 * Daniel Silverstone <dsilvers@digital-scurf.org>
6 * Copyright 2004 Daniel Silverstone and Project Purple
8 * $Id: keydb_fs.c,v 1.3 2004/05/28 03:23:04 noodles Exp $
11 #include <sys/types.h>
23 #include "charfuncs.h"
26 #include "keystructs.h"
29 #include "onak-conf.h"
34 static int keydb_lockfile_fd = -1;
35 static bool keydb_lockfile_readonly;
37 /*****************************************************************************/
39 /* Helper functions */
41 #define FNV_offset_basis 2166136261ul
42 #define FNV_mixing_prime 16777619ul
44 static uint32_t calchash(uint8_t * ptr)
46 register uint32_t h = FNV_offset_basis;
47 register uint32_t p = FNV_mixing_prime;
48 register uint32_t n = strlen((char *) ptr);
49 register uint8_t *c = ptr;
54 return h ? h : 1; /* prevent a hash of zero happening */
58 void keypath(char *buffer, uint64_t _keyid)
60 uint64_t keyid = _keyid << 32;
61 snprintf(buffer, PATH_MAX, "%s/key/%02X/%02X/%08X/%016llX",
62 config.db_dir, (uint8_t) ((keyid >> 56) & 0xFF),
63 (uint8_t) ((keyid >> 48) & 0xFF),
64 (uint32_t) (keyid >> 32), _keyid);
67 void keydir(char *buffer, uint64_t _keyid)
69 uint64_t keyid = _keyid << 32;
70 snprintf(buffer, PATH_MAX, "%s/key/%02X/%02X/%08X", config.db_dir,
71 (uint8_t) ((keyid >> 56) & 0xFF),
72 (uint8_t) ((keyid >> 48) & 0xFF),
73 (uint32_t) (keyid >> 32));
76 void prove_path_to(uint64_t keyid, char *what)
78 static char buffer[1024];
79 snprintf(buffer, PATH_MAX, "%s/%s", config.db_dir, what);
82 snprintf(buffer, PATH_MAX, "%s/%s/%02X", config.db_dir, what,
83 (uint8_t) ((keyid >> 24) & 0xFF));
86 snprintf(buffer, PATH_MAX, "%s/%s/%02X/%02X", config.db_dir, what,
87 (uint8_t) ((keyid >> 24) & 0xFF),
88 (uint8_t) ((keyid >> 16) & 0xFF));
91 snprintf(buffer, PATH_MAX, "%s/%s/%02X/%02X/%08X", config.db_dir, what,
92 (uint8_t) ((keyid >> 24) & 0xFF),
93 (uint8_t) ((keyid >> 16) & 0xFF), (uint32_t) (keyid));
97 void wordpath(char *buffer, char *word, uint32_t hash, uint64_t keyid)
99 snprintf(buffer, PATH_MAX, "%s/words/%02X/%02X/%08X/%s/%016llX",
100 config.db_dir, (uint8_t) ((hash >> 24) & 0xFF),
101 (uint8_t) ((hash >> 16) & 0xFF), hash, word, keyid);
104 void worddir(char *buffer, char *word, uint32_t hash)
106 snprintf(buffer, PATH_MAX, "%s/words/%02X/%02X/%08X/%s", config.db_dir,
107 (uint8_t) ((hash >> 24) & 0xFF),
108 (uint8_t) ((hash >> 16) & 0xFF), hash, word);
111 /*****************************************************************************/
114 * initdb - Initialize the key database.
116 void initdb(bool readonly)
118 char buffer[PATH_MAX];
120 keydb_lockfile_readonly = readonly;
122 snprintf(buffer, PATH_MAX, "%s/.lock", config.db_dir);
124 if (access(config.db_dir, R_OK | W_OK | X_OK) == -1) {
125 if (errno != ENOENT) {
126 logthing(LOGTHING_CRITICAL,
127 "Unable to access keydb_fs root of '%s'. (%s)",
128 config.db_dir, strerror(errno));
129 exit(1); /* Lacking rwx on the key dir */
131 mkdir(config.db_dir, 0777);
132 keydb_lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
134 chdir(config.db_dir);
135 if (keydb_lockfile_fd == -1)
136 keydb_lockfile_fd = open(buffer,
137 (keydb_lockfile_readonly) ?
139 if (keydb_lockfile_fd == -1)
140 keydb_lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
141 if (keydb_lockfile_fd == -1) {
142 logthing(LOGTHING_CRITICAL,
143 "Unable to open lockfile '%s'. (%s)",
144 buffer, strerror(errno));
145 exit(1); /* Lacking rwx on the key dir */
150 * cleanupdb - De-initialize the key database.
154 /* Mmmm nothing to do here? */
155 close(keydb_lockfile_fd);
159 * starttrans - Start a transaction.
161 bool starttrans(void)
163 struct flock lockstruct;
166 F_RDLCK | ((keydb_lockfile_readonly) ? 0 : F_WRLCK);
167 lockstruct.l_whence = SEEK_SET;
168 lockstruct.l_start = 0;
169 lockstruct.l_len = 1;
171 while (fcntl(keydb_lockfile_fd, F_SETLK, &lockstruct) == -1) {
172 if (remaining-- == 0)
173 return false; /* Hope to hell that noodles DTRT */
180 * endtrans - End a transaction.
184 struct flock lockstruct;
186 lockstruct.l_type = F_UNLCK;
187 lockstruct.l_whence = SEEK_SET;
188 lockstruct.l_start = 0;
189 lockstruct.l_len = 1;
190 fcntl(keydb_lockfile_fd, F_SETLK, &lockstruct);
194 * fetch_key - Given a keyid fetch the key from storage.
195 * @keyid: The keyid to fetch.
196 * @publickey: A pointer to a structure to return the key in.
197 * @intrans: If we're already in a transaction.
199 int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
202 static char buffer[PATH_MAX];
204 struct openpgp_packet_list *packets = NULL;
209 if ((keyid >> 32) == 0)
210 keyid = getfullkeyid(keyid);
212 keypath(buffer, keyid);
213 if ((fd = open(buffer, O_RDONLY)) != -1) {
214 /* File is present, load it in... */
215 read_openpgp_stream(file_fetchchar, &fd, &packets, 0);
216 parse_keys(packets, publickey);
217 free_packet_list(packets);
229 * store_key - Takes a key and stores it.
230 * @publickey: A pointer to the public key to store.
231 * @intrans: If we're already in a transaction.
232 * @update: If true the key exists and should be updated.
234 int store_key(struct openpgp_publickey *publickey, bool intrans,
237 static char buffer[PATH_MAX];
238 static char wbuffer[PATH_MAX];
240 struct openpgp_packet_list *packets = NULL;
241 struct openpgp_packet_list *list_end = NULL;
242 struct openpgp_publickey *next = NULL;
243 uint64_t keyid = get_keyid(publickey);
244 struct ll *wordlist = NULL, *wl = NULL;
250 prove_path_to(keyid, "key");
251 keypath(buffer, keyid);
254 open(buffer, O_WRONLY | (update ? O_TRUNC : O_CREAT),
256 next = publickey->next;
257 publickey->next = NULL;
258 flatten_publickey(publickey, &packets, &list_end);
259 publickey->next = next;
261 write_openpgp_stream(file_putchar, &fd, packets);
263 free_packet_list(packets);
269 wl = wordlist = makewordlistfromkey(wordlist, publickey);
271 uint32_t hash = calchash((uint8_t *) (wl->object));
272 prove_path_to(hash, "words");
274 worddir(wbuffer, wl->object, hash);
275 mkdir(wbuffer, 0777);
276 wordpath(wbuffer, wl->object, hash, keyid);
277 link(buffer, wbuffer);
282 llfree(wordlist, free);
291 * delete_key - Given a keyid delete the key from storage.
292 * @keyid: The keyid to delete.
293 * @intrans: If we're already in a transaction.
295 int delete_key(uint64_t keyid, bool intrans)
297 static char buffer[PATH_MAX];
299 struct openpgp_publickey *pk = NULL;
300 struct ll *wordlist = NULL, *wl = NULL;
302 if ((keyid >> 32) == 0)
303 keyid = getfullkeyid(keyid);
308 ret = fetch_key(keyid, &pk, true);
311 logthing(LOGTHING_CRITICAL, "Wordlist for key %016llX",
313 wl = wordlist = makewordlistfromkey(wordlist, pk);
314 logthing(LOGTHING_CRITICAL,
315 "Wordlist for key %016llX done", keyid);
317 uint32_t hash = calchash((uint8_t *) (wl->object));
318 prove_path_to(hash, "words");
320 wordpath(buffer, wl->object, hash, keyid);
327 keypath(buffer, keyid);
335 static struct ll *internal_get_key_by_word(char *word, struct ll *mct)
337 struct ll *keys = NULL;
339 char buffer[PATH_MAX];
340 uint32_t hash = calchash((uint8_t *) (word));
343 worddir(buffer, word, hash);
345 logthing(LOGTHING_CRITICAL, "Scanning for word %s in dir %s", word,
350 if (de && de->d_name[0] != '.') {
352 || (llfind(mct, de->d_name, strcmp) !=
354 logthing(LOGTHING_CRITICAL,
355 "Found %s // %s", word,
369 * fetch_key_text - Trys to find the keys that contain the supplied text.
370 * @search: The text to search for.
371 * @publickey: A pointer to a structure to return the key in.
373 int fetch_key_text(const char *search,
374 struct openpgp_publickey **publickey)
376 struct ll *wordlist = NULL, *wl = NULL;
377 struct ll *keylist = NULL;
378 char *searchtext = NULL;
381 logthing(LOGTHING_CRITICAL, "Search was '%s'", search);
383 searchtext = strdup(search);
384 wl = wordlist = makewordlist(wordlist, searchtext);
386 keylist = internal_get_key_by_word(wordlist->object, NULL);
389 llfree(wordlist, NULL);
398 internal_get_key_by_word(wl->object, keylist);
400 llfree(wordlist, NULL);
401 llfree(keylist, free);
406 llfree(keylist, free);
411 llfree(wordlist, NULL);
413 /* Now add the keys... */
416 logthing(LOGTHING_CRITICAL, "Adding key: %s", wl->object);
418 fetch_key(strtoull(wl->object, NULL, 16), publickey,
420 if (addedkeys >= config.maxkeys)
425 llfree(keylist, free);
433 * dumpdb - dump the key database
434 * @filenamebase: The base filename to use for the dump.
436 int dumpdb(char *filenamebase)
441 uint64_t getfullkeyid(uint64_t keyid)
443 static char buffer[PATH_MAX];
448 keydir(buffer, keyid);
454 if (de && de->d_name[0] != '.') {
455 ret = strtoull(de->d_name, NULL, 16);
457 } while (de && de->d_name[0] == '.');
463 * Include the basic keydb routines.
465 #define NEED_KEYID2UID 1
466 #define NEED_GETKEYSIGS 1