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 if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
278 logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
283 keyd_delete_key(keyid, false);
286 write(keyd_fd, &cmd, sizeof(cmd));
287 read(keyd_fd, &cmd, sizeof(cmd));
288 if (cmd == KEYD_REPLY_OK) {
291 keybuf.buffer = malloc(keybuf.size);
293 next = publickey->next;
294 publickey->next = NULL;
295 flatten_publickey(publickey,
298 publickey->next = next;
300 write_openpgp_stream(buffer_putchar, &keybuf, packets);
301 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
302 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
303 write(keyd_fd, keybuf.buffer, keybuf.offset);
305 free_packet_list(packets);
306 packets = list_end = NULL;
308 keybuf.buffer = NULL;
309 keybuf.size = keybuf.offset = 0;
316 * fetch_key_text - Trys to find the keys that contain the supplied text.
317 * @search: The text to search for.
318 * @publickey: A pointer to a structure to return the key in.
320 * This function searches for the supplied text and returns the keys that
323 static int keyd_fetch_key_text(const char *search,
324 struct openpgp_publickey **publickey)
326 struct buffer_ctx keybuf;
327 struct openpgp_packet_list *packets = NULL;
328 uint32_t cmd = KEYD_CMD_GETTEXT;
332 write(keyd_fd, &cmd, sizeof(cmd));
333 read(keyd_fd, &cmd, sizeof(cmd));
334 if (cmd == KEYD_REPLY_OK) {
335 bytes = strlen(search);
336 write(keyd_fd, &bytes, sizeof(bytes));
337 write(keyd_fd, search, bytes);
339 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
340 if (keybuf.size > 0) {
341 keybuf.buffer = malloc(keybuf.size);
343 logthing(LOGTHING_TRACE,
344 "Getting %d bytes of key data.",
346 while (bytes >= 0 && count < keybuf.size) {
347 bytes = read(keyd_fd, &keybuf.buffer[count],
348 keybuf.size - count);
349 logthing(LOGTHING_TRACE,
350 "Read %d bytes.", bytes);
353 read_openpgp_stream(buffer_fetchchar, &keybuf,
355 parse_keys(packets, publickey);
356 free_packet_list(packets);
359 keybuf.buffer = NULL;
364 return (count > 0) ? 1 : 0;
369 static int keyd_fetch_key_skshash(const struct skshash *hash,
370 struct openpgp_publickey **publickey)
372 struct buffer_ctx keybuf;
373 struct openpgp_packet_list *packets = NULL;
374 uint32_t cmd = KEYD_CMD_GETSKSHASH;
378 write(keyd_fd, &cmd, sizeof(cmd));
379 read(keyd_fd, &cmd, sizeof(cmd));
380 if (cmd == KEYD_REPLY_OK) {
381 write(keyd_fd, hash->hash, sizeof(hash->hash));
383 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
384 if (keybuf.size > 0) {
385 keybuf.buffer = malloc(keybuf.size);
387 logthing(LOGTHING_TRACE,
388 "Getting %d bytes of key data.",
390 while (bytes >= 0 && count < keybuf.size) {
391 bytes = read(keyd_fd, &keybuf.buffer[count],
392 keybuf.size - count);
393 logthing(LOGTHING_TRACE,
394 "Read %d bytes.", bytes);
397 read_openpgp_stream(buffer_fetchchar, &keybuf,
399 parse_keys(packets, publickey);
400 free_packet_list(packets);
403 keybuf.buffer = NULL;
408 return (count > 0) ? 1 : 0;
413 * getfullkeyid - Maps a 32bit key id to a 64bit one.
414 * @keyid: The 32bit keyid.
416 * This function maps a 32bit key id to the full 64bit one. It returns the
417 * full keyid. If the key isn't found a keyid of 0 is returned.
419 static uint64_t keyd_getfullkeyid(uint64_t keyid)
421 uint32_t cmd = KEYD_CMD_GETFULLKEYID;
423 write(keyd_fd, &cmd, sizeof(cmd));
424 read(keyd_fd, &cmd, sizeof(cmd));
425 if (cmd == KEYD_REPLY_OK) {
426 write(keyd_fd, &keyid, sizeof(keyid));
427 read(keyd_fd, &cmd, sizeof(cmd));
428 if (cmd != sizeof(keyid)) {
431 read(keyd_fd, &keyid, sizeof(keyid));
438 * iterate_keys - call a function once for each key in the db.
439 * @iterfunc: The function to call.
440 * @ctx: A context pointer
442 * Calls iterfunc once for each key in the database. ctx is passed
443 * unaltered to iterfunc. This function is intended to aid database dumps
444 * and statistic calculations.
446 * Returns the number of keys we iterated over.
448 static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
449 struct openpgp_publickey *key), void *ctx)
451 struct buffer_ctx keybuf;
452 struct openpgp_packet_list *packets = NULL;
453 struct openpgp_publickey *key = NULL;
454 uint32_t cmd = KEYD_CMD_KEYITER;
459 write(keyd_fd, &cmd, sizeof(cmd));
460 read(keyd_fd, &cmd, sizeof(cmd));
461 if (cmd == KEYD_REPLY_OK) {
463 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
464 while (keybuf.size > 0) {
465 keybuf.buffer = malloc(keybuf.size);
467 logthing(LOGTHING_TRACE,
468 "Getting %d bytes of key data.",
470 while (bytes >= 0 && count < keybuf.size) {
471 bytes = read(keyd_fd, &keybuf.buffer[count],
472 keybuf.size - count);
473 logthing(LOGTHING_TRACE,
474 "Read %d bytes.", bytes);
477 read_openpgp_stream(buffer_fetchchar, &keybuf,
479 parse_keys(packets, &key);
481 if (iterfunc != NULL && key != NULL) {
487 free_packet_list(packets);
490 keybuf.buffer = NULL;
491 keybuf.size = keybuf.offset = 0;
495 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
502 #define NEED_KEYID2UID 1
503 #define NEED_GETKEYSIGS 1
504 #define NEED_UPDATEKEYS 1
507 struct dbfuncs keydb_keyd_funcs = {
508 .initdb = keyd_initdb,
509 .cleanupdb = keyd_cleanupdb,
510 .starttrans = keyd_starttrans,
511 .endtrans = keyd_endtrans,
512 .fetch_key = keyd_fetch_key,
513 .fetch_key_text = keyd_fetch_key_text,
514 .fetch_key_skshash = keyd_fetch_key_skshash,
515 .store_key = keyd_store_key,
516 .update_keys = generic_update_keys,
517 .delete_key = keyd_delete_key,
518 .getkeysigs = generic_getkeysigs,
519 .cached_getkeysigs = generic_cached_getkeysigs,
520 .keyid2uid = generic_keyid2uid,
521 .getfullkeyid = keyd_getfullkeyid,
522 .iterate_keys = keyd_iterate_keys,