2 * keydb.h - Routines to store and fetch keys.
4 * Daniel Silverstone <dsilvers@digital-scurf.org>
6 * Copyright 2004 Daniel Silverstone and Project Purple
21 #include "charfuncs.h"
24 #include "keystructs.h"
27 #include "onak-conf.h"
32 static int keydb_lockfile_fd = -1;
33 static bool keydb_lockfile_readonly;
35 /*****************************************************************************/
37 /* Helper functions */
39 #define FNV_offset_basis 2166136261ul
40 #define FNV_mixing_prime 16777619ul
42 static uint32_t calchash(uint8_t * ptr)
44 register uint32_t h = FNV_offset_basis;
45 register uint32_t p = FNV_mixing_prime;
46 register uint32_t n = strlen((char *) ptr);
47 register uint8_t *c = ptr;
52 return h ? h : 1; /* prevent a hash of zero happening */
56 void keypath(char *buffer, uint64_t _keyid)
58 uint64_t keyid = _keyid << 32;
59 snprintf(buffer, PATH_MAX, "%s/key/%02X/%02X/%08X/%016llX",
60 config.db_dir, (uint8_t) ((keyid >> 56) & 0xFF),
61 (uint8_t) ((keyid >> 48) & 0xFF),
62 (uint32_t) (keyid >> 32), _keyid);
65 void keydir(char *buffer, uint64_t _keyid)
67 uint64_t keyid = _keyid << 32;
68 snprintf(buffer, PATH_MAX, "%s/key/%02X/%02X/%08X", config.db_dir,
69 (uint8_t) ((keyid >> 56) & 0xFF),
70 (uint8_t) ((keyid >> 48) & 0xFF),
71 (uint32_t) (keyid >> 32));
74 void prove_path_to(uint64_t keyid, char *what)
76 static char buffer[1024];
77 snprintf(buffer, PATH_MAX, "%s/%s", config.db_dir, what);
80 snprintf(buffer, PATH_MAX, "%s/%s/%02X", config.db_dir, what,
81 (uint8_t) ((keyid >> 24) & 0xFF));
84 snprintf(buffer, PATH_MAX, "%s/%s/%02X/%02X", config.db_dir, what,
85 (uint8_t) ((keyid >> 24) & 0xFF),
86 (uint8_t) ((keyid >> 16) & 0xFF));
89 snprintf(buffer, PATH_MAX, "%s/%s/%02X/%02X/%08X", config.db_dir, what,
90 (uint8_t) ((keyid >> 24) & 0xFF),
91 (uint8_t) ((keyid >> 16) & 0xFF), (uint32_t) (keyid));
95 void wordpath(char *buffer, char *word, uint32_t hash, uint64_t keyid)
97 snprintf(buffer, PATH_MAX, "%s/words/%02X/%02X/%08X/%s/%016llX",
98 config.db_dir, (uint8_t) ((hash >> 24) & 0xFF),
99 (uint8_t) ((hash >> 16) & 0xFF), hash, word, keyid);
102 void worddir(char *buffer, char *word, uint32_t hash)
104 snprintf(buffer, PATH_MAX, "%s/words/%02X/%02X/%08X/%s", config.db_dir,
105 (uint8_t) ((hash >> 24) & 0xFF),
106 (uint8_t) ((hash >> 16) & 0xFF), hash, word);
109 /*****************************************************************************/
112 * initdb - Initialize the key database.
114 void initdb(bool readonly)
116 char buffer[PATH_MAX];
118 keydb_lockfile_readonly = readonly;
120 snprintf(buffer, PATH_MAX, "%s/.lock", config.db_dir);
122 if (access(config.db_dir, R_OK | W_OK | X_OK) == -1) {
123 if (errno != ENOENT) {
124 logthing(LOGTHING_CRITICAL,
125 "Unable to access keydb_fs root of '%s'. (%s)",
126 config.db_dir, strerror(errno));
127 exit(1); /* Lacking rwx on the key dir */
129 mkdir(config.db_dir, 0777);
130 keydb_lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
132 chdir(config.db_dir);
133 if (keydb_lockfile_fd == -1)
134 keydb_lockfile_fd = open(buffer,
135 (keydb_lockfile_readonly) ?
137 if (keydb_lockfile_fd == -1)
138 keydb_lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
139 if (keydb_lockfile_fd == -1) {
140 logthing(LOGTHING_CRITICAL,
141 "Unable to open lockfile '%s'. (%s)",
142 buffer, strerror(errno));
143 exit(1); /* Lacking rwx on the key dir */
148 * cleanupdb - De-initialize the key database.
152 /* Mmmm nothing to do here? */
153 close(keydb_lockfile_fd);
157 * starttrans - Start a transaction.
159 bool starttrans(void)
161 struct flock lockstruct;
164 F_RDLCK | ((keydb_lockfile_readonly) ? 0 : F_WRLCK);
165 lockstruct.l_whence = SEEK_SET;
166 lockstruct.l_start = 0;
167 lockstruct.l_len = 1;
169 while (fcntl(keydb_lockfile_fd, F_SETLK, &lockstruct) == -1) {
170 if (remaining-- == 0)
171 return false; /* Hope to hell that noodles DTRT */
178 * endtrans - End a transaction.
182 struct flock lockstruct;
184 lockstruct.l_type = F_UNLCK;
185 lockstruct.l_whence = SEEK_SET;
186 lockstruct.l_start = 0;
187 lockstruct.l_len = 1;
188 fcntl(keydb_lockfile_fd, F_SETLK, &lockstruct);
192 * fetch_key - Given a keyid fetch the key from storage.
193 * @keyid: The keyid to fetch.
194 * @publickey: A pointer to a structure to return the key in.
195 * @intrans: If we're already in a transaction.
197 int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
200 static char buffer[PATH_MAX];
202 struct openpgp_packet_list *packets = NULL;
207 if ((keyid >> 32) == 0)
208 keyid = getfullkeyid(keyid);
210 keypath(buffer, keyid);
211 if ((fd = open(buffer, O_RDONLY)) != -1) {
212 /* File is present, load it in... */
213 read_openpgp_stream(file_fetchchar, &fd, &packets, 0);
214 parse_keys(packets, publickey);
215 free_packet_list(packets);
227 * store_key - Takes a key and stores it.
228 * @publickey: A pointer to the public key to store.
229 * @intrans: If we're already in a transaction.
230 * @update: If true the key exists and should be updated.
232 int store_key(struct openpgp_publickey *publickey, bool intrans,
235 static char buffer[PATH_MAX];
236 static char wbuffer[PATH_MAX];
238 struct openpgp_packet_list *packets = NULL;
239 struct openpgp_packet_list *list_end = NULL;
240 struct openpgp_publickey *next = NULL;
241 uint64_t keyid = get_keyid(publickey);
242 struct ll *wordlist = NULL, *wl = NULL;
248 prove_path_to(keyid, "key");
249 keypath(buffer, keyid);
252 open(buffer, O_WRONLY | (update ? O_TRUNC : O_CREAT),
254 next = publickey->next;
255 publickey->next = NULL;
256 flatten_publickey(publickey, &packets, &list_end);
257 publickey->next = next;
259 write_openpgp_stream(file_putchar, &fd, packets);
261 free_packet_list(packets);
267 wl = wordlist = makewordlistfromkey(wordlist, publickey);
269 uint32_t hash = calchash((uint8_t *) (wl->object));
270 prove_path_to(hash, "words");
272 worddir(wbuffer, wl->object, hash);
273 mkdir(wbuffer, 0777);
274 wordpath(wbuffer, wl->object, hash, keyid);
275 link(buffer, wbuffer);
280 llfree(wordlist, free);
289 * delete_key - Given a keyid delete the key from storage.
290 * @keyid: The keyid to delete.
291 * @intrans: If we're already in a transaction.
293 int delete_key(uint64_t keyid, bool intrans)
295 static char buffer[PATH_MAX];
297 struct openpgp_publickey *pk = NULL;
298 struct ll *wordlist = NULL, *wl = NULL;
300 if ((keyid >> 32) == 0)
301 keyid = getfullkeyid(keyid);
306 ret = fetch_key(keyid, &pk, true);
309 logthing(LOGTHING_CRITICAL, "Wordlist for key %016llX",
311 wl = wordlist = makewordlistfromkey(wordlist, pk);
312 logthing(LOGTHING_CRITICAL,
313 "Wordlist for key %016llX done", keyid);
315 uint32_t hash = calchash((uint8_t *) (wl->object));
316 prove_path_to(hash, "words");
318 wordpath(buffer, wl->object, hash, keyid);
325 keypath(buffer, keyid);
333 static struct ll *internal_get_key_by_word(char *word, struct ll *mct)
335 struct ll *keys = NULL;
337 char buffer[PATH_MAX];
338 uint32_t hash = calchash((uint8_t *) (word));
341 worddir(buffer, word, hash);
343 logthing(LOGTHING_CRITICAL, "Scanning for word %s in dir %s", word,
348 if (de && de->d_name[0] != '.') {
350 || (llfind(mct, de->d_name, strcmp) !=
352 logthing(LOGTHING_CRITICAL,
353 "Found %s // %s", word,
367 * fetch_key_text - Trys to find the keys that contain the supplied text.
368 * @search: The text to search for.
369 * @publickey: A pointer to a structure to return the key in.
371 int fetch_key_text(const char *search,
372 struct openpgp_publickey **publickey)
374 struct ll *wordlist = NULL, *wl = NULL;
375 struct ll *keylist = NULL;
376 char *searchtext = NULL;
379 logthing(LOGTHING_CRITICAL, "Search was '%s'", search);
381 searchtext = strdup(search);
382 wl = wordlist = makewordlist(wordlist, searchtext);
384 keylist = internal_get_key_by_word(wordlist->object, NULL);
387 llfree(wordlist, NULL);
396 internal_get_key_by_word(wl->object, keylist);
398 llfree(wordlist, NULL);
399 llfree(keylist, free);
404 llfree(keylist, free);
409 llfree(wordlist, NULL);
411 /* Now add the keys... */
414 logthing(LOGTHING_CRITICAL, "Adding key: %s", wl->object);
416 fetch_key(strtoull(wl->object, NULL, 16), publickey,
418 if (addedkeys >= config.maxkeys)
423 llfree(keylist, free);
431 * dumpdb - dump the key database
432 * @filenamebase: The base filename to use for the dump.
434 int dumpdb(char *filenamebase)
439 uint64_t getfullkeyid(uint64_t keyid)
441 static char buffer[PATH_MAX];
446 keydir(buffer, keyid);
452 if (de && de->d_name[0] != '.') {
453 ret = strtoull(de->d_name, NULL, 16);
455 } while (de && de->d_name[0] == '.');
461 * Include the basic keydb routines.
463 #define NEED_KEYID2UID 1
464 #define NEED_GETKEYSIGS 1