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",
119 if (close(keyd_fd) < 0) {
120 logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
130 * starttrans - Start a transaction.
132 * Start a transaction. Intended to be used if we're about to perform many
133 * operations on the database to help speed it all up, or if we want
134 * something to only succeed if all relevant operations are successful.
136 static bool keyd_starttrans(void)
142 * endtrans - End a transaction.
144 * Ends a transaction.
146 static void keyd_endtrans(void)
152 * fetch_key - Given a keyid fetch the key from storage.
153 * @keyid: The keyid to fetch.
154 * @publickey: A pointer to a structure to return the key in.
155 * @intrans: If we're already in a transaction.
157 * This function returns a public key from whatever storage mechanism we
160 * TODO: What about keyid collisions? Should we use fingerprint instead?
162 static int keyd_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
165 struct buffer_ctx keybuf;
166 struct openpgp_packet_list *packets = NULL;
167 int cmd = KEYD_CMD_GET;
171 write(keyd_fd, &cmd, sizeof(cmd));
172 read(keyd_fd, &cmd, sizeof(cmd));
173 if (cmd == KEYD_REPLY_OK) {
174 write(keyd_fd, &keyid, sizeof(keyid));
176 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
177 if (keybuf.size > 0) {
178 keybuf.buffer = malloc(keybuf.size);
180 logthing(LOGTHING_TRACE,
181 "Getting %d bytes of key data.",
183 while (bytes >= 0 && count < keybuf.size) {
184 bytes = read(keyd_fd, &keybuf.buffer[count],
185 keybuf.size - count);
186 logthing(LOGTHING_TRACE,
187 "Read %d bytes.", bytes);
190 read_openpgp_stream(buffer_fetchchar, &keybuf,
192 parse_keys(packets, publickey);
193 free_packet_list(packets);
196 keybuf.buffer = NULL;
201 return (count > 0) ? 1 : 0;
205 * delete_key - Given a keyid delete the key from storage.
206 * @keyid: The keyid to delete.
207 * @intrans: If we're already in a transaction.
209 * This function deletes a public key from whatever storage mechanism we
210 * are using. Returns 0 if the key existed.
212 static int keyd_delete_key(uint64_t keyid, bool intrans)
214 int cmd = KEYD_CMD_DELETE;
216 write(keyd_fd, &cmd, sizeof(cmd));
217 read(keyd_fd, &cmd, sizeof(cmd));
218 if (cmd == KEYD_REPLY_OK) {
219 write(keyd_fd, &keyid, sizeof(keyid));
226 * store_key - Takes a key and stores it.
227 * @publickey: A pointer to the public key to store.
228 * @intrans: If we're already in a transaction.
229 * @update: If true the key exists and should be updated.
231 * This function stores a public key in whatever storage mechanism we are
232 * using. intrans indicates if we're already in a transaction so don't
233 * need to start one. update indicates if the key already exists and is
234 * just being updated.
236 * TODO: Do we store multiple keys of the same id? Or only one and replace
239 static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
242 struct buffer_ctx keybuf;
243 struct openpgp_packet_list *packets = NULL;
244 struct openpgp_packet_list *list_end = NULL;
245 struct openpgp_publickey *next = NULL;
246 int cmd = KEYD_CMD_STORE;
249 keyid = get_keyid(publickey);
252 keyd_delete_key(keyid, false);
255 write(keyd_fd, &cmd, sizeof(cmd));
256 read(keyd_fd, &cmd, sizeof(cmd));
257 if (cmd == KEYD_REPLY_OK) {
260 keybuf.buffer = malloc(keybuf.size);
262 next = publickey->next;
263 publickey->next = NULL;
264 flatten_publickey(publickey,
267 publickey->next = next;
269 write_openpgp_stream(buffer_putchar, &keybuf, packets);
270 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
271 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
272 write(keyd_fd, keybuf.buffer, keybuf.offset);
274 free_packet_list(packets);
275 packets = list_end = NULL;
277 keybuf.buffer = NULL;
278 keybuf.size = keybuf.offset = 0;
285 * fetch_key_text - Trys to find the keys that contain the supplied text.
286 * @search: The text to search for.
287 * @publickey: A pointer to a structure to return the key in.
289 * This function searches for the supplied text and returns the keys that
292 static int keyd_fetch_key_text(const char *search,
293 struct openpgp_publickey **publickey)
295 struct buffer_ctx keybuf;
296 struct openpgp_packet_list *packets = NULL;
297 int cmd = KEYD_CMD_GETTEXT;
301 write(keyd_fd, &cmd, sizeof(cmd));
302 read(keyd_fd, &cmd, sizeof(cmd));
303 if (cmd == KEYD_REPLY_OK) {
304 bytes = strlen(search);
305 write(keyd_fd, &bytes, sizeof(bytes));
306 write(keyd_fd, search, bytes);
308 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
309 if (keybuf.size > 0) {
310 keybuf.buffer = malloc(keybuf.size);
312 logthing(LOGTHING_TRACE,
313 "Getting %d bytes of key data.",
315 while (bytes >= 0 && count < keybuf.size) {
316 bytes = read(keyd_fd, &keybuf.buffer[count],
317 keybuf.size - count);
318 logthing(LOGTHING_TRACE,
319 "Read %d bytes.", bytes);
322 read_openpgp_stream(buffer_fetchchar, &keybuf,
324 parse_keys(packets, publickey);
325 free_packet_list(packets);
328 keybuf.buffer = NULL;
333 return (count > 0) ? 1 : 0;
339 * getfullkeyid - Maps a 32bit key id to a 64bit one.
340 * @keyid: The 32bit keyid.
342 * This function maps a 32bit key id to the full 64bit one. It returns the
343 * full keyid. If the key isn't found a keyid of 0 is returned.
345 static uint64_t keyd_getfullkeyid(uint64_t keyid)
347 int cmd = KEYD_CMD_GETFULLKEYID;
349 write(keyd_fd, &cmd, sizeof(cmd));
350 read(keyd_fd, &cmd, sizeof(cmd));
351 if (cmd == KEYD_REPLY_OK) {
352 write(keyd_fd, &keyid, sizeof(keyid));
353 read(keyd_fd, &keyid, sizeof(keyid));
360 * iterate_keys - call a function once for each key in the db.
361 * @iterfunc: The function to call.
362 * @ctx: A context pointer
364 * Calls iterfunc once for each key in the database. ctx is passed
365 * unaltered to iterfunc. This function is intended to aid database dumps
366 * and statistic calculations.
368 * Returns the number of keys we iterated over.
370 static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
371 struct openpgp_publickey *key), void *ctx)
373 struct buffer_ctx keybuf;
374 struct openpgp_packet_list *packets = NULL;
375 struct openpgp_publickey *key = NULL;
376 int cmd = KEYD_CMD_KEYITER;
381 write(keyd_fd, &cmd, sizeof(cmd));
382 read(keyd_fd, &cmd, sizeof(cmd));
383 if (cmd == KEYD_REPLY_OK) {
385 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
386 while (keybuf.size > 0) {
387 keybuf.buffer = malloc(keybuf.size);
389 logthing(LOGTHING_TRACE,
390 "Getting %d bytes of key data.",
392 while (bytes >= 0 && count < keybuf.size) {
393 bytes = read(keyd_fd, &keybuf.buffer[count],
394 keybuf.size - count);
395 logthing(LOGTHING_TRACE,
396 "Read %d bytes.", bytes);
399 read_openpgp_stream(buffer_fetchchar, &keybuf,
401 parse_keys(packets, &key);
403 if (iterfunc != NULL && key != NULL) {
409 free_packet_list(packets);
412 keybuf.buffer = NULL;
413 keybuf.size = keybuf.offset = 0;
417 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
424 #define NEED_KEYID2UID 1
425 #define NEED_GETKEYSIGS 1
426 #define NEED_UPDATEKEYS 1
429 struct dbfuncs keydb_keyd_funcs = {
430 .initdb = keyd_initdb,
431 .cleanupdb = keyd_cleanupdb,
432 .starttrans = keyd_starttrans,
433 .endtrans = keyd_endtrans,
434 .fetch_key = keyd_fetch_key,
435 .fetch_key_text = keyd_fetch_key_text,
436 .store_key = keyd_store_key,
437 .update_keys = generic_update_keys,
438 .delete_key = keyd_delete_key,
439 .getkeysigs = generic_getkeysigs,
440 .cached_getkeysigs = generic_cached_getkeysigs,
441 .keyid2uid = generic_keyid2uid,
442 .getfullkeyid = keyd_getfullkeyid,
443 .iterate_keys = keyd_iterate_keys,