2 * keydb_keyd.c - Routines to talk to keyd backend.
4 * Jonathan McDowell <noodles@earth.li>
6 * Copyright 2004 Project Purple
14 #include <sys/socket.h>
15 #include <sys/types.h>
19 #include "charfuncs.h"
23 #include "keystructs.h"
26 #include "onak-conf.h"
30 * keyd_fd - our file descriptor for the socket connection to keyd.
32 static int keyd_fd = -1;
35 * initdb - Initialize the key database.
36 * @readonly: If we'll only be reading the DB, not writing to it.
38 * This function should be called before any of the other functions in
39 * this file are called in order to allow the DB to be initialized ready
42 static void keyd_initdb(bool readonly)
44 struct sockaddr_un sock;
45 uint32_t cmd = KEYD_CMD_UNKNOWN;
46 uint32_t reply = KEYD_REPLY_UNKNOWN_CMD;
49 keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
51 logthing(LOGTHING_CRITICAL,
52 "Couldn't open socket: %s (%d)",
58 sock.sun_family = AF_UNIX;
59 snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
62 if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
63 logthing(LOGTHING_CRITICAL,
64 "Couldn't connect to socket %s: %s (%d)",
71 cmd = KEYD_CMD_VERSION;
72 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
73 logthing(LOGTHING_CRITICAL,
74 "Couldn't write version cmd: %s (%d)",
78 count = read(keyd_fd, &reply, sizeof(reply));
79 if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
80 count = read(keyd_fd, &reply, sizeof(reply));
81 if (count != sizeof(reply) || reply != sizeof(reply)) {
82 logthing(LOGTHING_CRITICAL,
83 "Error! Unexpected keyd version "
85 reply, sizeof(reply));
89 count = read(keyd_fd, &reply, sizeof(reply));
90 logthing(LOGTHING_DEBUG,
91 "keyd protocol version %d",
93 if (reply != keyd_version) {
94 logthing(LOGTHING_CRITICAL,
95 "Error! keyd protocol version "
96 "mismatch. (us = %d, it = %d)",
106 * cleanupdb - De-initialize the key database.
108 * This function should be called upon program exit to allow the DB to
109 * cleanup after itself.
111 static void keyd_cleanupdb(void)
113 uint32_t cmd = KEYD_CMD_CLOSE;
115 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
116 logthing(LOGTHING_CRITICAL,
117 "Couldn't send close cmd: %s (%d)",
122 if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
123 logthing(LOGTHING_CRITICAL,
124 "Couldn't read close cmd reply: %s (%d)",
127 } else if (cmd != KEYD_REPLY_OK) {
128 logthing(LOGTHING_CRITICAL,
129 "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
132 if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
133 logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
136 if (close(keyd_fd) < 0) {
137 logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
147 * starttrans - Start a transaction.
149 * Start a transaction. Intended to be used if we're about to perform many
150 * operations on the database to help speed it all up, or if we want
151 * something to only succeed if all relevant operations are successful.
153 static bool keyd_starttrans(void)
159 * endtrans - End a transaction.
161 * Ends a transaction.
163 static void keyd_endtrans(void)
169 * fetch_key - Given a keyid fetch the key from storage.
170 * @keyid: The keyid to fetch.
171 * @publickey: A pointer to a structure to return the key in.
172 * @intrans: If we're already in a transaction.
174 * This function returns a public key from whatever storage mechanism we
177 * TODO: What about keyid collisions? Should we use fingerprint instead?
179 static int keyd_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
182 struct buffer_ctx keybuf;
183 struct openpgp_packet_list *packets = NULL;
184 uint32_t cmd = KEYD_CMD_GET;
188 write(keyd_fd, &cmd, sizeof(cmd));
189 read(keyd_fd, &cmd, sizeof(cmd));
190 if (cmd == KEYD_REPLY_OK) {
191 write(keyd_fd, &keyid, sizeof(keyid));
193 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
194 if (keybuf.size > 0) {
195 keybuf.buffer = malloc(keybuf.size);
197 logthing(LOGTHING_TRACE,
198 "Getting %d bytes of key data.",
200 while (bytes >= 0 && count < keybuf.size) {
201 bytes = read(keyd_fd, &keybuf.buffer[count],
202 keybuf.size - count);
203 logthing(LOGTHING_TRACE,
204 "Read %d bytes.", bytes);
207 read_openpgp_stream(buffer_fetchchar, &keybuf,
209 parse_keys(packets, publickey);
210 free_packet_list(packets);
213 keybuf.buffer = NULL;
218 return (count > 0) ? 1 : 0;
222 * delete_key - Given a keyid delete the key from storage.
223 * @keyid: The keyid to delete.
224 * @intrans: If we're already in a transaction.
226 * This function deletes a public key from whatever storage mechanism we
227 * are using. Returns 0 if the key existed.
229 static int keyd_delete_key(uint64_t keyid, bool intrans)
231 uint32_t cmd = KEYD_CMD_DELETE;
233 write(keyd_fd, &cmd, sizeof(cmd));
234 read(keyd_fd, &cmd, sizeof(cmd));
235 if (cmd == KEYD_REPLY_OK) {
236 write(keyd_fd, &keyid, sizeof(keyid));
243 * store_key - Takes a key and stores it.
244 * @publickey: A pointer to the public key to store.
245 * @intrans: If we're already in a transaction.
246 * @update: If true the key exists and should be updated.
248 * This function stores a public key in whatever storage mechanism we are
249 * using. intrans indicates if we're already in a transaction so don't
250 * need to start one. update indicates if the key already exists and is
251 * just being updated.
253 * TODO: Do we store multiple keys of the same id? Or only one and replace
256 static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
259 struct buffer_ctx keybuf;
260 struct openpgp_packet_list *packets = NULL;
261 struct openpgp_packet_list *list_end = NULL;
262 struct openpgp_publickey *next = NULL;
263 uint32_t cmd = KEYD_CMD_STORE;
266 keyid = get_keyid(publickey);
269 keyd_delete_key(keyid, false);
272 write(keyd_fd, &cmd, sizeof(cmd));
273 read(keyd_fd, &cmd, sizeof(cmd));
274 if (cmd == KEYD_REPLY_OK) {
277 keybuf.buffer = malloc(keybuf.size);
279 next = publickey->next;
280 publickey->next = NULL;
281 flatten_publickey(publickey,
284 publickey->next = next;
286 write_openpgp_stream(buffer_putchar, &keybuf, packets);
287 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
288 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
289 write(keyd_fd, keybuf.buffer, keybuf.offset);
291 free_packet_list(packets);
292 packets = list_end = NULL;
294 keybuf.buffer = NULL;
295 keybuf.size = keybuf.offset = 0;
302 * fetch_key_text - Trys to find the keys that contain the supplied text.
303 * @search: The text to search for.
304 * @publickey: A pointer to a structure to return the key in.
306 * This function searches for the supplied text and returns the keys that
309 static int keyd_fetch_key_text(const char *search,
310 struct openpgp_publickey **publickey)
312 struct buffer_ctx keybuf;
313 struct openpgp_packet_list *packets = NULL;
314 uint32_t cmd = KEYD_CMD_GETTEXT;
318 write(keyd_fd, &cmd, sizeof(cmd));
319 read(keyd_fd, &cmd, sizeof(cmd));
320 if (cmd == KEYD_REPLY_OK) {
321 bytes = strlen(search);
322 write(keyd_fd, &bytes, sizeof(bytes));
323 write(keyd_fd, search, bytes);
325 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
326 if (keybuf.size > 0) {
327 keybuf.buffer = malloc(keybuf.size);
329 logthing(LOGTHING_TRACE,
330 "Getting %d bytes of key data.",
332 while (bytes >= 0 && count < keybuf.size) {
333 bytes = read(keyd_fd, &keybuf.buffer[count],
334 keybuf.size - count);
335 logthing(LOGTHING_TRACE,
336 "Read %d bytes.", bytes);
339 read_openpgp_stream(buffer_fetchchar, &keybuf,
341 parse_keys(packets, publickey);
342 free_packet_list(packets);
345 keybuf.buffer = NULL;
350 return (count > 0) ? 1 : 0;
356 * getfullkeyid - Maps a 32bit key id to a 64bit one.
357 * @keyid: The 32bit keyid.
359 * This function maps a 32bit key id to the full 64bit one. It returns the
360 * full keyid. If the key isn't found a keyid of 0 is returned.
362 static uint64_t keyd_getfullkeyid(uint64_t keyid)
364 uint32_t cmd = KEYD_CMD_GETFULLKEYID;
366 write(keyd_fd, &cmd, sizeof(cmd));
367 read(keyd_fd, &cmd, sizeof(cmd));
368 if (cmd == KEYD_REPLY_OK) {
369 write(keyd_fd, &keyid, sizeof(keyid));
370 read(keyd_fd, &cmd, sizeof(cmd));
371 if (cmd != sizeof(keyid)) {
374 read(keyd_fd, &keyid, sizeof(keyid));
381 * iterate_keys - call a function once for each key in the db.
382 * @iterfunc: The function to call.
383 * @ctx: A context pointer
385 * Calls iterfunc once for each key in the database. ctx is passed
386 * unaltered to iterfunc. This function is intended to aid database dumps
387 * and statistic calculations.
389 * Returns the number of keys we iterated over.
391 static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
392 struct openpgp_publickey *key), void *ctx)
394 struct buffer_ctx keybuf;
395 struct openpgp_packet_list *packets = NULL;
396 struct openpgp_publickey *key = NULL;
397 uint32_t cmd = KEYD_CMD_KEYITER;
402 write(keyd_fd, &cmd, sizeof(cmd));
403 read(keyd_fd, &cmd, sizeof(cmd));
404 if (cmd == KEYD_REPLY_OK) {
406 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
407 while (keybuf.size > 0) {
408 keybuf.buffer = malloc(keybuf.size);
410 logthing(LOGTHING_TRACE,
411 "Getting %d bytes of key data.",
413 while (bytes >= 0 && count < keybuf.size) {
414 bytes = read(keyd_fd, &keybuf.buffer[count],
415 keybuf.size - count);
416 logthing(LOGTHING_TRACE,
417 "Read %d bytes.", bytes);
420 read_openpgp_stream(buffer_fetchchar, &keybuf,
422 parse_keys(packets, &key);
424 if (iterfunc != NULL && key != NULL) {
430 free_packet_list(packets);
433 keybuf.buffer = NULL;
434 keybuf.size = keybuf.offset = 0;
438 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
445 #define NEED_KEYID2UID 1
446 #define NEED_GETKEYSIGS 1
447 #define NEED_UPDATEKEYS 1
450 struct dbfuncs keydb_keyd_funcs = {
451 .initdb = keyd_initdb,
452 .cleanupdb = keyd_cleanupdb,
453 .starttrans = keyd_starttrans,
454 .endtrans = keyd_endtrans,
455 .fetch_key = keyd_fetch_key,
456 .fetch_key_text = keyd_fetch_key_text,
457 .store_key = keyd_store_key,
458 .update_keys = generic_update_keys,
459 .delete_key = keyd_delete_key,
460 .getkeysigs = generic_getkeysigs,
461 .cached_getkeysigs = generic_cached_getkeysigs,
462 .keyid2uid = generic_keyid2uid,
463 .getfullkeyid = keyd_getfullkeyid,
464 .iterate_keys = keyd_iterate_keys,