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 int cmd = KEYD_CMD_UNKNOWN;
46 int 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)) {
80 if (reply == KEYD_REPLY_OK) {
81 count = read(keyd_fd, &reply, sizeof(reply));
82 logthing(LOGTHING_DEBUG,
83 "keyd protocol version %d",
85 if (reply != keyd_version) {
86 logthing(LOGTHING_CRITICAL,
87 "Error! keyd protocol version "
88 "mismatch. (us = %d, it = %d)",
99 * cleanupdb - De-initialize the key database.
101 * This function should be called upon program exit to allow the DB to
102 * cleanup after itself.
104 static void keyd_cleanupdb(void)
106 int cmd = KEYD_CMD_CLOSE;
108 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
109 logthing(LOGTHING_CRITICAL,
110 "Couldn't send close cmd: %s (%d)",
115 if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
116 logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
126 * starttrans - Start a transaction.
128 * Start a transaction. Intended to be used if we're about to perform many
129 * operations on the database to help speed it all up, or if we want
130 * something to only succeed if all relevant operations are successful.
132 static bool keyd_starttrans(void)
138 * endtrans - End a transaction.
140 * Ends a transaction.
142 static void keyd_endtrans(void)
148 * fetch_key - Given a keyid fetch the key from storage.
149 * @keyid: The keyid to fetch.
150 * @publickey: A pointer to a structure to return the key in.
151 * @intrans: If we're already in a transaction.
153 * This function returns a public key from whatever storage mechanism we
156 * TODO: What about keyid collisions? Should we use fingerprint instead?
158 static int keyd_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
161 struct buffer_ctx keybuf;
162 struct openpgp_packet_list *packets = NULL;
163 int cmd = KEYD_CMD_GET;
167 write(keyd_fd, &cmd, sizeof(cmd));
168 read(keyd_fd, &cmd, sizeof(cmd));
169 if (cmd == KEYD_REPLY_OK) {
170 write(keyd_fd, &keyid, sizeof(keyid));
172 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
173 if (keybuf.size > 0) {
174 keybuf.buffer = malloc(keybuf.size);
176 logthing(LOGTHING_TRACE,
177 "Getting %d bytes of key data.",
179 while (bytes >= 0 && count < keybuf.size) {
180 bytes = read(keyd_fd, &keybuf.buffer[count],
181 keybuf.size - count);
182 logthing(LOGTHING_TRACE,
183 "Read %d bytes.", bytes);
186 read_openpgp_stream(buffer_fetchchar, &keybuf,
188 parse_keys(packets, publickey);
189 free_packet_list(packets);
192 keybuf.buffer = NULL;
197 return (count > 0) ? 1 : 0;
201 * delete_key - Given a keyid delete the key from storage.
202 * @keyid: The keyid to delete.
203 * @intrans: If we're already in a transaction.
205 * This function deletes a public key from whatever storage mechanism we
206 * are using. Returns 0 if the key existed.
208 static int keyd_delete_key(uint64_t keyid, bool intrans)
210 int cmd = KEYD_CMD_DELETE;
212 write(keyd_fd, &cmd, sizeof(cmd));
213 read(keyd_fd, &cmd, sizeof(cmd));
214 if (cmd == KEYD_REPLY_OK) {
215 write(keyd_fd, &keyid, sizeof(keyid));
222 * store_key - Takes a key and stores it.
223 * @publickey: A pointer to the public key to store.
224 * @intrans: If we're already in a transaction.
225 * @update: If true the key exists and should be updated.
227 * This function stores a public key in whatever storage mechanism we are
228 * using. intrans indicates if we're already in a transaction so don't
229 * need to start one. update indicates if the key already exists and is
230 * just being updated.
232 * TODO: Do we store multiple keys of the same id? Or only one and replace
235 static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
238 struct buffer_ctx keybuf;
239 struct openpgp_packet_list *packets = NULL;
240 struct openpgp_packet_list *list_end = NULL;
241 struct openpgp_publickey *next = NULL;
242 int cmd = KEYD_CMD_STORE;
245 keyid = get_keyid(publickey);
248 keyd_delete_key(keyid, false);
251 write(keyd_fd, &cmd, sizeof(cmd));
252 read(keyd_fd, &cmd, sizeof(cmd));
253 if (cmd == KEYD_REPLY_OK) {
256 keybuf.buffer = malloc(keybuf.size);
258 next = publickey->next;
259 publickey->next = NULL;
260 flatten_publickey(publickey,
263 publickey->next = next;
265 write_openpgp_stream(buffer_putchar, &keybuf, packets);
266 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
267 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
268 write(keyd_fd, keybuf.buffer, keybuf.offset);
270 free_packet_list(packets);
271 packets = list_end = NULL;
273 keybuf.buffer = NULL;
274 keybuf.size = keybuf.offset = 0;
281 * fetch_key_text - Trys to find the keys that contain the supplied text.
282 * @search: The text to search for.
283 * @publickey: A pointer to a structure to return the key in.
285 * This function searches for the supplied text and returns the keys that
288 static int keyd_fetch_key_text(const char *search,
289 struct openpgp_publickey **publickey)
291 struct buffer_ctx keybuf;
292 struct openpgp_packet_list *packets = NULL;
293 int cmd = KEYD_CMD_GETTEXT;
297 write(keyd_fd, &cmd, sizeof(cmd));
298 read(keyd_fd, &cmd, sizeof(cmd));
299 if (cmd == KEYD_REPLY_OK) {
300 bytes = strlen(search);
301 write(keyd_fd, &bytes, sizeof(bytes));
302 write(keyd_fd, search, bytes);
304 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
305 if (keybuf.size > 0) {
306 keybuf.buffer = malloc(keybuf.size);
308 logthing(LOGTHING_TRACE,
309 "Getting %d bytes of key data.",
311 while (bytes >= 0 && count < keybuf.size) {
312 bytes = read(keyd_fd, &keybuf.buffer[count],
313 keybuf.size - count);
314 logthing(LOGTHING_TRACE,
315 "Read %d bytes.", bytes);
318 read_openpgp_stream(buffer_fetchchar, &keybuf,
320 parse_keys(packets, publickey);
321 free_packet_list(packets);
324 keybuf.buffer = NULL;
329 return (count > 0) ? 1 : 0;
335 * getfullkeyid - Maps a 32bit key id to a 64bit one.
336 * @keyid: The 32bit keyid.
338 * This function maps a 32bit key id to the full 64bit one. It returns the
339 * full keyid. If the key isn't found a keyid of 0 is returned.
341 static uint64_t keyd_getfullkeyid(uint64_t keyid)
343 int cmd = KEYD_CMD_GETFULLKEYID;
345 write(keyd_fd, &cmd, sizeof(cmd));
346 read(keyd_fd, &cmd, sizeof(cmd));
347 if (cmd == KEYD_REPLY_OK) {
348 write(keyd_fd, &keyid, sizeof(keyid));
349 read(keyd_fd, &keyid, sizeof(keyid));
356 * iterate_keys - call a function once for each key in the db.
357 * @iterfunc: The function to call.
358 * @ctx: A context pointer
360 * Calls iterfunc once for each key in the database. ctx is passed
361 * unaltered to iterfunc. This function is intended to aid database dumps
362 * and statistic calculations.
364 * Returns the number of keys we iterated over.
366 static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
367 struct openpgp_publickey *key), void *ctx)
369 struct buffer_ctx keybuf;
370 struct openpgp_packet_list *packets = NULL;
371 struct openpgp_publickey *key = NULL;
372 int cmd = KEYD_CMD_KEYITER;
377 write(keyd_fd, &cmd, sizeof(cmd));
378 read(keyd_fd, &cmd, sizeof(cmd));
379 if (cmd == KEYD_REPLY_OK) {
381 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
382 while (keybuf.size > 0) {
383 keybuf.buffer = malloc(keybuf.size);
385 logthing(LOGTHING_TRACE,
386 "Getting %d bytes of key data.",
388 while (bytes >= 0 && count < keybuf.size) {
389 bytes = read(keyd_fd, &keybuf.buffer[count],
390 keybuf.size - count);
391 logthing(LOGTHING_TRACE,
392 "Read %d bytes.", bytes);
395 read_openpgp_stream(buffer_fetchchar, &keybuf,
397 parse_keys(packets, &key);
399 if (iterfunc != NULL && key != NULL) {
405 free_packet_list(packets);
408 keybuf.buffer = NULL;
409 keybuf.size = keybuf.offset = 0;
413 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
420 #define NEED_KEYID2UID 1
421 #define NEED_GETKEYSIGS 1
422 #define NEED_UPDATEKEYS 1
425 struct dbfuncs keydb_keyd_funcs = {
426 .initdb = keyd_initdb,
427 .cleanupdb = keyd_cleanupdb,
428 .starttrans = keyd_starttrans,
429 .endtrans = keyd_endtrans,
430 .fetch_key = keyd_fetch_key,
431 .fetch_key_text = keyd_fetch_key_text,
432 .store_key = keyd_store_key,
433 .update_keys = generic_update_keys,
434 .delete_key = keyd_delete_key,
435 .getkeysigs = generic_getkeysigs,
436 .cached_getkeysigs = generic_cached_getkeysigs,
437 .keyid2uid = generic_keyid2uid,
438 .getfullkeyid = keyd_getfullkeyid,
439 .iterate_keys = keyd_iterate_keys,