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(uint64_t keyid, struct openpgp_publickey **publickey,
193 struct buffer_ctx keybuf;
194 struct openpgp_packet_list *packets = NULL;
195 uint32_t cmd = KEYD_CMD_GET;
199 write(keyd_fd, &cmd, sizeof(cmd));
200 read(keyd_fd, &cmd, sizeof(cmd));
201 if (cmd == KEYD_REPLY_OK) {
202 write(keyd_fd, &keyid, sizeof(keyid));
204 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
205 if (keybuf.size > 0) {
206 keybuf.buffer = malloc(keybuf.size);
208 logthing(LOGTHING_TRACE,
209 "Getting %d bytes of key data.",
211 while (bytes >= 0 && count < keybuf.size) {
212 bytes = read(keyd_fd, &keybuf.buffer[count],
213 keybuf.size - count);
214 logthing(LOGTHING_TRACE,
215 "Read %d bytes.", bytes);
218 read_openpgp_stream(buffer_fetchchar, &keybuf,
220 parse_keys(packets, publickey);
221 free_packet_list(packets);
224 keybuf.buffer = NULL;
229 return (count > 0) ? 1 : 0;
233 * delete_key - Given a keyid delete the key from storage.
234 * @keyid: The keyid to delete.
235 * @intrans: If we're already in a transaction.
237 * This function deletes a public key from whatever storage mechanism we
238 * are using. Returns 0 if the key existed.
240 static int keyd_delete_key(uint64_t keyid, bool intrans)
242 uint32_t cmd = KEYD_CMD_DELETE;
244 write(keyd_fd, &cmd, sizeof(cmd));
245 read(keyd_fd, &cmd, sizeof(cmd));
246 if (cmd == KEYD_REPLY_OK) {
247 write(keyd_fd, &keyid, sizeof(keyid));
254 * store_key - Takes a key and stores it.
255 * @publickey: A pointer to the public key to store.
256 * @intrans: If we're already in a transaction.
257 * @update: If true the key exists and should be updated.
259 * This function stores a public key in whatever storage mechanism we are
260 * using. intrans indicates if we're already in a transaction so don't
261 * need to start one. update indicates if the key already exists and is
262 * just being updated.
264 * TODO: Do we store multiple keys of the same id? Or only one and replace
267 static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
270 struct buffer_ctx keybuf;
271 struct openpgp_packet_list *packets = NULL;
272 struct openpgp_packet_list *list_end = NULL;
273 struct openpgp_publickey *next = NULL;
274 uint32_t cmd = KEYD_CMD_STORE;
277 keyid = get_keyid(publickey);
280 keyd_delete_key(keyid, false);
283 write(keyd_fd, &cmd, sizeof(cmd));
284 read(keyd_fd, &cmd, sizeof(cmd));
285 if (cmd == KEYD_REPLY_OK) {
288 keybuf.buffer = malloc(keybuf.size);
290 next = publickey->next;
291 publickey->next = NULL;
292 flatten_publickey(publickey,
295 publickey->next = next;
297 write_openpgp_stream(buffer_putchar, &keybuf, packets);
298 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
299 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
300 write(keyd_fd, keybuf.buffer, keybuf.offset);
302 free_packet_list(packets);
303 packets = list_end = NULL;
305 keybuf.buffer = NULL;
306 keybuf.size = keybuf.offset = 0;
313 * fetch_key_text - Trys to find the keys that contain the supplied text.
314 * @search: The text to search for.
315 * @publickey: A pointer to a structure to return the key in.
317 * This function searches for the supplied text and returns the keys that
320 static int keyd_fetch_key_text(const char *search,
321 struct openpgp_publickey **publickey)
323 struct buffer_ctx keybuf;
324 struct openpgp_packet_list *packets = NULL;
325 uint32_t cmd = KEYD_CMD_GETTEXT;
329 write(keyd_fd, &cmd, sizeof(cmd));
330 read(keyd_fd, &cmd, sizeof(cmd));
331 if (cmd == KEYD_REPLY_OK) {
332 bytes = strlen(search);
333 write(keyd_fd, &bytes, sizeof(bytes));
334 write(keyd_fd, search, bytes);
336 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
337 if (keybuf.size > 0) {
338 keybuf.buffer = malloc(keybuf.size);
340 logthing(LOGTHING_TRACE,
341 "Getting %d bytes of key data.",
343 while (bytes >= 0 && count < keybuf.size) {
344 bytes = read(keyd_fd, &keybuf.buffer[count],
345 keybuf.size - count);
346 logthing(LOGTHING_TRACE,
347 "Read %d bytes.", bytes);
350 read_openpgp_stream(buffer_fetchchar, &keybuf,
352 parse_keys(packets, publickey);
353 free_packet_list(packets);
356 keybuf.buffer = NULL;
361 return (count > 0) ? 1 : 0;
366 static int keyd_fetch_key_skshash(const struct skshash *hash,
367 struct openpgp_publickey **publickey)
369 struct buffer_ctx keybuf;
370 struct openpgp_packet_list *packets = NULL;
371 uint32_t cmd = KEYD_CMD_GETSKSHASH;
375 write(keyd_fd, &cmd, sizeof(cmd));
376 read(keyd_fd, &cmd, sizeof(cmd));
377 if (cmd == KEYD_REPLY_OK) {
378 write(keyd_fd, hash->hash, sizeof(hash->hash));
380 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
381 if (keybuf.size > 0) {
382 keybuf.buffer = malloc(keybuf.size);
384 logthing(LOGTHING_TRACE,
385 "Getting %d bytes of key data.",
387 while (bytes >= 0 && count < keybuf.size) {
388 bytes = read(keyd_fd, &keybuf.buffer[count],
389 keybuf.size - count);
390 logthing(LOGTHING_TRACE,
391 "Read %d bytes.", bytes);
394 read_openpgp_stream(buffer_fetchchar, &keybuf,
396 parse_keys(packets, publickey);
397 free_packet_list(packets);
400 keybuf.buffer = NULL;
405 return (count > 0) ? 1 : 0;
410 * getfullkeyid - Maps a 32bit key id to a 64bit one.
411 * @keyid: The 32bit keyid.
413 * This function maps a 32bit key id to the full 64bit one. It returns the
414 * full keyid. If the key isn't found a keyid of 0 is returned.
416 static uint64_t keyd_getfullkeyid(uint64_t keyid)
418 uint32_t cmd = KEYD_CMD_GETFULLKEYID;
420 write(keyd_fd, &cmd, sizeof(cmd));
421 read(keyd_fd, &cmd, sizeof(cmd));
422 if (cmd == KEYD_REPLY_OK) {
423 write(keyd_fd, &keyid, sizeof(keyid));
424 read(keyd_fd, &cmd, sizeof(cmd));
425 if (cmd != sizeof(keyid)) {
428 read(keyd_fd, &keyid, sizeof(keyid));
435 * iterate_keys - call a function once for each key in the db.
436 * @iterfunc: The function to call.
437 * @ctx: A context pointer
439 * Calls iterfunc once for each key in the database. ctx is passed
440 * unaltered to iterfunc. This function is intended to aid database dumps
441 * and statistic calculations.
443 * Returns the number of keys we iterated over.
445 static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
446 struct openpgp_publickey *key), void *ctx)
448 struct buffer_ctx keybuf;
449 struct openpgp_packet_list *packets = NULL;
450 struct openpgp_publickey *key = NULL;
451 uint32_t cmd = KEYD_CMD_KEYITER;
456 write(keyd_fd, &cmd, sizeof(cmd));
457 read(keyd_fd, &cmd, sizeof(cmd));
458 if (cmd == KEYD_REPLY_OK) {
460 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
461 while (keybuf.size > 0) {
462 keybuf.buffer = malloc(keybuf.size);
464 logthing(LOGTHING_TRACE,
465 "Getting %d bytes of key data.",
467 while (bytes >= 0 && count < keybuf.size) {
468 bytes = read(keyd_fd, &keybuf.buffer[count],
469 keybuf.size - count);
470 logthing(LOGTHING_TRACE,
471 "Read %d bytes.", bytes);
474 read_openpgp_stream(buffer_fetchchar, &keybuf,
476 parse_keys(packets, &key);
478 if (iterfunc != NULL && key != NULL) {
484 free_packet_list(packets);
487 keybuf.buffer = NULL;
488 keybuf.size = keybuf.offset = 0;
492 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
499 #define NEED_KEYID2UID 1
500 #define NEED_GETKEYSIGS 1
501 #define NEED_UPDATEKEYS 1
504 struct dbfuncs keydb_keyd_funcs = {
505 .initdb = keyd_initdb,
506 .cleanupdb = keyd_cleanupdb,
507 .starttrans = keyd_starttrans,
508 .endtrans = keyd_endtrans,
509 .fetch_key = keyd_fetch_key,
510 .fetch_key_text = keyd_fetch_key_text,
511 .fetch_key_skshash = keyd_fetch_key_skshash,
512 .store_key = keyd_store_key,
513 .update_keys = generic_update_keys,
514 .delete_key = keyd_delete_key,
515 .getkeysigs = generic_getkeysigs,
516 .cached_getkeysigs = generic_cached_getkeysigs,
517 .keyid2uid = generic_keyid2uid,
518 .getfullkeyid = keyd_getfullkeyid,
519 .iterate_keys = keyd_iterate_keys,