2 * keydb_keyd.c - Routines to talk to keyd backend.
4 * Copyright 2002-2004,2011 Jonathan McDowell <noodles@earth.li>
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 51
17 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include <sys/socket.h>
26 #include <sys/types.h>
30 #include "charfuncs.h"
34 #include "keystructs.h"
37 #include "onak-conf.h"
41 * keyd_fd - our file descriptor for the socket connection to keyd.
43 static int keyd_fd = -1;
46 * initdb - Initialize the key database.
47 * @readonly: If we'll only be reading the DB, not writing to it.
49 * This function should be called before any of the other functions in
50 * this file are called in order to allow the DB to be initialized ready
53 static void keyd_initdb(bool readonly)
55 struct sockaddr_un sock;
56 uint32_t cmd = KEYD_CMD_UNKNOWN;
57 uint32_t reply = KEYD_REPLY_UNKNOWN_CMD;
60 keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
62 logthing(LOGTHING_CRITICAL,
63 "Couldn't open socket: %s (%d)",
69 sock.sun_family = AF_UNIX;
70 snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
73 if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
74 logthing(LOGTHING_CRITICAL,
75 "Couldn't connect to socket %s: %s (%d)",
82 cmd = KEYD_CMD_VERSION;
83 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
84 logthing(LOGTHING_CRITICAL,
85 "Couldn't write version cmd: %s (%d)",
89 count = read(keyd_fd, &reply, sizeof(reply));
90 if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
91 count = read(keyd_fd, &reply, sizeof(reply));
92 if (count != sizeof(reply) || reply != sizeof(reply)) {
93 logthing(LOGTHING_CRITICAL,
94 "Error! Unexpected keyd version "
96 reply, sizeof(reply));
100 count = read(keyd_fd, &reply, sizeof(reply));
101 logthing(LOGTHING_DEBUG,
102 "keyd protocol version %d",
104 if (reply != keyd_version) {
105 logthing(LOGTHING_CRITICAL,
106 "Error! keyd protocol version "
107 "mismatch. (us = %d, it = %d)",
108 keyd_version, reply);
117 * cleanupdb - De-initialize the key database.
119 * This function should be called upon program exit to allow the DB to
120 * cleanup after itself.
122 static void keyd_cleanupdb(void)
124 uint32_t cmd = KEYD_CMD_CLOSE;
126 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
127 logthing(LOGTHING_CRITICAL,
128 "Couldn't send close cmd: %s (%d)",
133 if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
134 logthing(LOGTHING_CRITICAL,
135 "Couldn't read close cmd reply: %s (%d)",
138 } else if (cmd != KEYD_REPLY_OK) {
139 logthing(LOGTHING_CRITICAL,
140 "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
143 if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
144 logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
147 if (close(keyd_fd) < 0) {
148 logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
158 * starttrans - Start a transaction.
160 * Start a transaction. Intended to be used if we're about to perform many
161 * operations on the database to help speed it all up, or if we want
162 * something to only succeed if all relevant operations are successful.
164 static bool keyd_starttrans(void)
170 * endtrans - End a transaction.
172 * Ends a transaction.
174 static void keyd_endtrans(void)
180 * fetch_key - Given a keyid fetch the key from storage.
181 * @keyid: The keyid to fetch.
182 * @publickey: A pointer to a structure to return the key in.
183 * @intrans: If we're already in a transaction.
185 * This function returns a public key from whatever storage mechanism we
188 * TODO: What about keyid collisions? Should we use fingerprint instead?
190 static int keyd_fetch_key_id(uint64_t keyid,
191 struct openpgp_publickey **publickey,
194 struct buffer_ctx keybuf;
195 struct openpgp_packet_list *packets = NULL;
196 uint32_t cmd = KEYD_CMD_GET_ID;
200 write(keyd_fd, &cmd, sizeof(cmd));
201 read(keyd_fd, &cmd, sizeof(cmd));
202 if (cmd == KEYD_REPLY_OK) {
203 write(keyd_fd, &keyid, sizeof(keyid));
205 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
206 if (keybuf.size > 0) {
207 keybuf.buffer = malloc(keybuf.size);
209 logthing(LOGTHING_TRACE,
210 "Getting %d bytes of key data.",
212 while (bytes >= 0 && count < keybuf.size) {
213 bytes = read(keyd_fd, &keybuf.buffer[count],
214 keybuf.size - count);
215 logthing(LOGTHING_TRACE,
216 "Read %d bytes.", bytes);
219 read_openpgp_stream(buffer_fetchchar, &keybuf,
221 parse_keys(packets, publickey);
222 free_packet_list(packets);
225 keybuf.buffer = NULL;
230 return (count > 0) ? 1 : 0;
233 static int keyd_fetch_key_fp(uint8_t *fp, size_t fpsize,
234 struct openpgp_publickey **publickey,
237 struct buffer_ctx keybuf;
238 struct openpgp_packet_list *packets = NULL;
239 uint32_t cmd = KEYD_CMD_GET_FP;
244 if (fpsize > MAX_FINGERPRINT_LEN) {
248 write(keyd_fd, &cmd, sizeof(cmd));
249 read(keyd_fd, &cmd, sizeof(cmd));
250 if (cmd == KEYD_REPLY_OK) {
252 write(keyd_fd, &size, sizeof(size));
253 write(keyd_fd, fp, size);
255 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
256 if (keybuf.size > 0) {
257 keybuf.buffer = malloc(keybuf.size);
259 logthing(LOGTHING_TRACE,
260 "Getting %d bytes of key data.",
262 while (bytes >= 0 && count < keybuf.size) {
263 bytes = read(keyd_fd, &keybuf.buffer[count],
264 keybuf.size - count);
265 logthing(LOGTHING_TRACE,
266 "Read %d bytes.", bytes);
269 read_openpgp_stream(buffer_fetchchar, &keybuf,
271 parse_keys(packets, publickey);
272 free_packet_list(packets);
275 keybuf.buffer = NULL;
280 return (count > 0) ? 1 : 0;
284 * delete_key - Given a keyid delete the key from storage.
285 * @keyid: The keyid to delete.
286 * @intrans: If we're already in a transaction.
288 * This function deletes a public key from whatever storage mechanism we
289 * are using. Returns 0 if the key existed.
291 static int keyd_delete_key(uint64_t keyid, bool intrans)
293 uint32_t cmd = KEYD_CMD_DELETE;
295 write(keyd_fd, &cmd, sizeof(cmd));
296 read(keyd_fd, &cmd, sizeof(cmd));
297 if (cmd == KEYD_REPLY_OK) {
298 write(keyd_fd, &keyid, sizeof(keyid));
305 * store_key - Takes a key and stores it.
306 * @publickey: A pointer to the public key to store.
307 * @intrans: If we're already in a transaction.
308 * @update: If true the key exists and should be updated.
310 * This function stores a public key in whatever storage mechanism we are
311 * using. intrans indicates if we're already in a transaction so don't
312 * need to start one. update indicates if the key already exists and is
313 * just being updated.
315 * TODO: Do we store multiple keys of the same id? Or only one and replace
318 static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
321 struct buffer_ctx keybuf;
322 struct openpgp_packet_list *packets = NULL;
323 struct openpgp_packet_list *list_end = NULL;
324 struct openpgp_publickey *next = NULL;
325 uint32_t cmd = KEYD_CMD_STORE;
328 if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
329 logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
334 keyd_delete_key(keyid, false);
337 write(keyd_fd, &cmd, sizeof(cmd));
338 read(keyd_fd, &cmd, sizeof(cmd));
339 if (cmd == KEYD_REPLY_OK) {
342 keybuf.buffer = malloc(keybuf.size);
344 next = publickey->next;
345 publickey->next = NULL;
346 flatten_publickey(publickey,
349 publickey->next = next;
351 write_openpgp_stream(buffer_putchar, &keybuf, packets);
352 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
353 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
354 write(keyd_fd, keybuf.buffer, keybuf.offset);
356 free_packet_list(packets);
357 packets = list_end = NULL;
359 keybuf.buffer = NULL;
360 keybuf.size = keybuf.offset = 0;
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 * This function searches for the supplied text and returns the keys that
374 static int keyd_fetch_key_text(const char *search,
375 struct openpgp_publickey **publickey)
377 struct buffer_ctx keybuf;
378 struct openpgp_packet_list *packets = NULL;
379 uint32_t cmd = KEYD_CMD_GET_TEXT;
383 write(keyd_fd, &cmd, sizeof(cmd));
384 read(keyd_fd, &cmd, sizeof(cmd));
385 if (cmd == KEYD_REPLY_OK) {
386 bytes = strlen(search);
387 write(keyd_fd, &bytes, sizeof(bytes));
388 write(keyd_fd, search, bytes);
390 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
391 if (keybuf.size > 0) {
392 keybuf.buffer = malloc(keybuf.size);
394 logthing(LOGTHING_TRACE,
395 "Getting %d bytes of key data.",
397 while (bytes >= 0 && count < keybuf.size) {
398 bytes = read(keyd_fd, &keybuf.buffer[count],
399 keybuf.size - count);
400 logthing(LOGTHING_TRACE,
401 "Read %d bytes.", bytes);
404 read_openpgp_stream(buffer_fetchchar, &keybuf,
406 parse_keys(packets, publickey);
407 free_packet_list(packets);
410 keybuf.buffer = NULL;
415 return (count > 0) ? 1 : 0;
420 static int keyd_fetch_key_skshash(const struct skshash *hash,
421 struct openpgp_publickey **publickey)
423 struct buffer_ctx keybuf;
424 struct openpgp_packet_list *packets = NULL;
425 uint32_t cmd = KEYD_CMD_GET_SKSHASH;
429 write(keyd_fd, &cmd, sizeof(cmd));
430 read(keyd_fd, &cmd, sizeof(cmd));
431 if (cmd == KEYD_REPLY_OK) {
432 write(keyd_fd, hash->hash, sizeof(hash->hash));
434 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
435 if (keybuf.size > 0) {
436 keybuf.buffer = malloc(keybuf.size);
438 logthing(LOGTHING_TRACE,
439 "Getting %d bytes of key data.",
441 while (bytes >= 0 && count < keybuf.size) {
442 bytes = read(keyd_fd, &keybuf.buffer[count],
443 keybuf.size - count);
444 logthing(LOGTHING_TRACE,
445 "Read %d bytes.", bytes);
448 read_openpgp_stream(buffer_fetchchar, &keybuf,
450 parse_keys(packets, publickey);
451 free_packet_list(packets);
454 keybuf.buffer = NULL;
459 return (count > 0) ? 1 : 0;
464 * getfullkeyid - Maps a 32bit key id to a 64bit one.
465 * @keyid: The 32bit keyid.
467 * This function maps a 32bit key id to the full 64bit one. It returns the
468 * full keyid. If the key isn't found a keyid of 0 is returned.
470 static uint64_t keyd_getfullkeyid(uint64_t keyid)
472 uint32_t cmd = KEYD_CMD_GETFULLKEYID;
474 write(keyd_fd, &cmd, sizeof(cmd));
475 read(keyd_fd, &cmd, sizeof(cmd));
476 if (cmd == KEYD_REPLY_OK) {
477 write(keyd_fd, &keyid, sizeof(keyid));
478 read(keyd_fd, &cmd, sizeof(cmd));
479 if (cmd != sizeof(keyid)) {
482 read(keyd_fd, &keyid, sizeof(keyid));
489 * iterate_keys - call a function once for each key in the db.
490 * @iterfunc: The function to call.
491 * @ctx: A context pointer
493 * Calls iterfunc once for each key in the database. ctx is passed
494 * unaltered to iterfunc. This function is intended to aid database dumps
495 * and statistic calculations.
497 * Returns the number of keys we iterated over.
499 static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
500 struct openpgp_publickey *key), void *ctx)
502 struct buffer_ctx keybuf;
503 struct openpgp_packet_list *packets = NULL;
504 struct openpgp_publickey *key = NULL;
505 uint32_t cmd = KEYD_CMD_KEYITER;
510 write(keyd_fd, &cmd, sizeof(cmd));
511 read(keyd_fd, &cmd, sizeof(cmd));
512 if (cmd == KEYD_REPLY_OK) {
514 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
515 while (keybuf.size > 0) {
516 keybuf.buffer = malloc(keybuf.size);
518 logthing(LOGTHING_TRACE,
519 "Getting %d bytes of key data.",
521 while (bytes >= 0 && count < keybuf.size) {
522 bytes = read(keyd_fd, &keybuf.buffer[count],
523 keybuf.size - count);
524 logthing(LOGTHING_TRACE,
525 "Read %d bytes.", bytes);
528 read_openpgp_stream(buffer_fetchchar, &keybuf,
530 parse_keys(packets, &key);
532 if (iterfunc != NULL && key != NULL) {
538 free_packet_list(packets);
541 keybuf.buffer = NULL;
542 keybuf.size = keybuf.offset = 0;
546 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
553 #define NEED_KEYID2UID 1
554 #define NEED_GETKEYSIGS 1
555 #define NEED_UPDATEKEYS 1
558 struct dbfuncs keydb_keyd_funcs = {
559 .initdb = keyd_initdb,
560 .cleanupdb = keyd_cleanupdb,
561 .starttrans = keyd_starttrans,
562 .endtrans = keyd_endtrans,
563 .fetch_key_id = keyd_fetch_key_id,
564 .fetch_key_fp = keyd_fetch_key_fp,
565 .fetch_key_text = keyd_fetch_key_text,
566 .fetch_key_skshash = keyd_fetch_key_skshash,
567 .store_key = keyd_store_key,
568 .update_keys = generic_update_keys,
569 .delete_key = keyd_delete_key,
570 .getkeysigs = generic_getkeysigs,
571 .cached_getkeysigs = generic_cached_getkeysigs,
572 .keyid2uid = generic_keyid2uid,
573 .getfullkeyid = keyd_getfullkeyid,
574 .iterate_keys = keyd_iterate_keys,