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 if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
107 logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
117 * starttrans - Start a transaction.
119 * Start a transaction. Intended to be used if we're about to perform many
120 * operations on the database to help speed it all up, or if we want
121 * something to only succeed if all relevant operations are successful.
123 static bool keyd_starttrans(void)
129 * endtrans - End a transaction.
131 * Ends a transaction.
133 static void keyd_endtrans(void)
139 * fetch_key - Given a keyid fetch the key from storage.
140 * @keyid: The keyid to fetch.
141 * @publickey: A pointer to a structure to return the key in.
142 * @intrans: If we're already in a transaction.
144 * This function returns a public key from whatever storage mechanism we
147 * TODO: What about keyid collisions? Should we use fingerprint instead?
149 static int keyd_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
152 struct buffer_ctx keybuf;
153 struct openpgp_packet_list *packets = NULL;
154 int cmd = KEYD_CMD_GET;
158 write(keyd_fd, &cmd, sizeof(cmd));
159 read(keyd_fd, &cmd, sizeof(cmd));
160 if (cmd == KEYD_REPLY_OK) {
161 write(keyd_fd, &keyid, sizeof(keyid));
163 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
164 if (keybuf.size > 0) {
165 keybuf.buffer = malloc(keybuf.size);
167 logthing(LOGTHING_TRACE,
168 "Getting %d bytes of key data.",
170 while (bytes >= 0 && count < keybuf.size) {
171 bytes = read(keyd_fd, &keybuf.buffer[count],
172 keybuf.size - count);
173 logthing(LOGTHING_TRACE,
174 "Read %d bytes.", bytes);
177 read_openpgp_stream(buffer_fetchchar, &keybuf,
179 parse_keys(packets, publickey);
180 free_packet_list(packets);
183 keybuf.buffer = NULL;
188 return (count > 0) ? 1 : 0;
192 * delete_key - Given a keyid delete the key from storage.
193 * @keyid: The keyid to delete.
194 * @intrans: If we're already in a transaction.
196 * This function deletes a public key from whatever storage mechanism we
197 * are using. Returns 0 if the key existed.
199 static int keyd_delete_key(uint64_t keyid, bool intrans)
201 int cmd = KEYD_CMD_DELETE;
203 write(keyd_fd, &cmd, sizeof(cmd));
204 read(keyd_fd, &cmd, sizeof(cmd));
205 if (cmd == KEYD_REPLY_OK) {
206 write(keyd_fd, &keyid, sizeof(keyid));
213 * store_key - Takes a key and stores it.
214 * @publickey: A pointer to the public key to store.
215 * @intrans: If we're already in a transaction.
216 * @update: If true the key exists and should be updated.
218 * This function stores a public key in whatever storage mechanism we are
219 * using. intrans indicates if we're already in a transaction so don't
220 * need to start one. update indicates if the key already exists and is
221 * just being updated.
223 * TODO: Do we store multiple keys of the same id? Or only one and replace
226 static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
229 struct buffer_ctx keybuf;
230 struct openpgp_packet_list *packets = NULL;
231 struct openpgp_packet_list *list_end = NULL;
232 struct openpgp_publickey *next = NULL;
233 int cmd = KEYD_CMD_STORE;
236 keyid = get_keyid(publickey);
239 keyd_delete_key(keyid, false);
242 write(keyd_fd, &cmd, sizeof(cmd));
243 read(keyd_fd, &cmd, sizeof(cmd));
244 if (cmd == KEYD_REPLY_OK) {
247 keybuf.buffer = malloc(keybuf.size);
249 next = publickey->next;
250 publickey->next = NULL;
251 flatten_publickey(publickey,
254 publickey->next = next;
256 write_openpgp_stream(buffer_putchar, &keybuf, packets);
257 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
258 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
259 write(keyd_fd, keybuf.buffer, keybuf.offset);
261 free_packet_list(packets);
262 packets = list_end = NULL;
264 keybuf.buffer = NULL;
265 keybuf.size = keybuf.offset = 0;
272 * fetch_key_text - Trys to find the keys that contain the supplied text.
273 * @search: The text to search for.
274 * @publickey: A pointer to a structure to return the key in.
276 * This function searches for the supplied text and returns the keys that
279 static int keyd_fetch_key_text(const char *search,
280 struct openpgp_publickey **publickey)
282 struct buffer_ctx keybuf;
283 struct openpgp_packet_list *packets = NULL;
284 int cmd = KEYD_CMD_GETTEXT;
288 write(keyd_fd, &cmd, sizeof(cmd));
289 read(keyd_fd, &cmd, sizeof(cmd));
290 if (cmd == KEYD_REPLY_OK) {
291 bytes = strlen(search);
292 write(keyd_fd, &bytes, sizeof(bytes));
293 write(keyd_fd, search, bytes);
295 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
296 if (keybuf.size > 0) {
297 keybuf.buffer = malloc(keybuf.size);
299 logthing(LOGTHING_TRACE,
300 "Getting %d bytes of key data.",
302 while (bytes >= 0 && count < keybuf.size) {
303 bytes = read(keyd_fd, &keybuf.buffer[count],
304 keybuf.size - count);
305 logthing(LOGTHING_TRACE,
306 "Read %d bytes.", bytes);
309 read_openpgp_stream(buffer_fetchchar, &keybuf,
311 parse_keys(packets, publickey);
312 free_packet_list(packets);
315 keybuf.buffer = NULL;
320 return (count > 0) ? 1 : 0;
326 * getfullkeyid - Maps a 32bit key id to a 64bit one.
327 * @keyid: The 32bit keyid.
329 * This function maps a 32bit key id to the full 64bit one. It returns the
330 * full keyid. If the key isn't found a keyid of 0 is returned.
332 static uint64_t keyd_getfullkeyid(uint64_t keyid)
334 int cmd = KEYD_CMD_GETFULLKEYID;
336 write(keyd_fd, &cmd, sizeof(cmd));
337 read(keyd_fd, &cmd, sizeof(cmd));
338 if (cmd == KEYD_REPLY_OK) {
339 write(keyd_fd, &keyid, sizeof(keyid));
340 read(keyd_fd, &keyid, sizeof(keyid));
347 * iterate_keys - call a function once for each key in the db.
348 * @iterfunc: The function to call.
349 * @ctx: A context pointer
351 * Calls iterfunc once for each key in the database. ctx is passed
352 * unaltered to iterfunc. This function is intended to aid database dumps
353 * and statistic calculations.
355 * Returns the number of keys we iterated over.
357 static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
358 struct openpgp_publickey *key), void *ctx)
360 struct buffer_ctx keybuf;
361 struct openpgp_packet_list *packets = NULL;
362 struct openpgp_publickey *key = NULL;
363 int cmd = KEYD_CMD_KEYITER;
368 write(keyd_fd, &cmd, sizeof(cmd));
369 read(keyd_fd, &cmd, sizeof(cmd));
370 if (cmd == KEYD_REPLY_OK) {
372 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
373 while (keybuf.size > 0) {
374 keybuf.buffer = malloc(keybuf.size);
376 logthing(LOGTHING_TRACE,
377 "Getting %d bytes of key data.",
379 while (bytes >= 0 && count < keybuf.size) {
380 bytes = read(keyd_fd, &keybuf.buffer[count],
381 keybuf.size - count);
382 logthing(LOGTHING_TRACE,
383 "Read %d bytes.", bytes);
386 read_openpgp_stream(buffer_fetchchar, &keybuf,
388 parse_keys(packets, &key);
390 if (iterfunc != NULL && key != NULL) {
396 free_packet_list(packets);
399 keybuf.buffer = NULL;
400 keybuf.size = keybuf.offset = 0;
404 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
411 #define NEED_KEYID2UID 1
412 #define NEED_GETKEYSIGS 1
413 #define NEED_UPDATEKEYS 1
416 struct dbfuncs keydb_keyd_funcs = {
417 .initdb = keyd_initdb,
418 .cleanupdb = keyd_cleanupdb,
419 .starttrans = keyd_starttrans,
420 .endtrans = keyd_endtrans,
421 .fetch_key = keyd_fetch_key,
422 .fetch_key_text = keyd_fetch_key_text,
423 .store_key = keyd_store_key,
424 .update_keys = generic_update_keys,
425 .delete_key = keyd_delete_key,
426 .getkeysigs = generic_getkeysigs,
427 .cached_getkeysigs = generic_cached_getkeysigs,
428 .keyid2uid = generic_keyid2uid,
429 .getfullkeyid = keyd_getfullkeyid,
430 .iterate_keys = keyd_iterate_keys,