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 * starttrans - Start a transaction.
43 * Start a transaction. Intended to be used if we're about to perform many
44 * operations on the database to help speed it all up, or if we want
45 * something to only succeed if all relevant operations are successful.
47 static bool keyd_starttrans(struct onak_dbctx *dbctx)
53 * endtrans - End a transaction.
57 static void keyd_endtrans(struct onak_dbctx *dbctx)
62 static bool keyd_send_cmd(int fd, enum keyd_ops _cmd)
67 bytes = write(fd, &cmd, sizeof(cmd));
68 if (bytes != sizeof(cmd)) {
72 bytes = read(fd, &cmd, sizeof(cmd));
73 if (bytes != sizeof(cmd)) {
77 if (cmd != KEYD_REPLY_OK) {
85 * fetch_key - Given a keyid fetch the key from storage.
86 * @keyid: The keyid to fetch.
87 * @publickey: A pointer to a structure to return the key in.
88 * @intrans: If we're already in a transaction.
90 * This function returns a public key from whatever storage mechanism we
93 * TODO: What about keyid collisions? Should we use fingerprint instead?
95 static int keyd_fetch_key_id(struct onak_dbctx *dbctx,
97 struct openpgp_publickey **publickey,
100 int keyd_fd = (intptr_t) dbctx->priv;
101 struct buffer_ctx keybuf;
102 struct openpgp_packet_list *packets = NULL;
106 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_ID)) {
107 write(keyd_fd, &keyid, sizeof(keyid));
109 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
110 if (keybuf.size > 0) {
111 keybuf.buffer = malloc(keybuf.size);
113 logthing(LOGTHING_TRACE,
114 "Getting %d bytes of key data.",
116 while (bytes >= 0 && count < keybuf.size) {
117 bytes = read(keyd_fd, &keybuf.buffer[count],
118 keybuf.size - count);
119 logthing(LOGTHING_TRACE,
120 "Read %d bytes.", bytes);
123 read_openpgp_stream(buffer_fetchchar, &keybuf,
125 parse_keys(packets, publickey);
126 free_packet_list(packets);
129 keybuf.buffer = NULL;
134 return (count > 0) ? 1 : 0;
137 static int keyd_fetch_key_fp(struct onak_dbctx *dbctx,
138 struct openpgp_fingerprint *fingerprint,
139 struct openpgp_publickey **publickey,
142 int keyd_fd = (intptr_t) dbctx->priv;
143 struct buffer_ctx keybuf;
144 struct openpgp_packet_list *packets = NULL;
149 if (fingerprint->length > MAX_FINGERPRINT_LEN) {
153 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_FP)) {
154 size = fingerprint->length;
155 write(keyd_fd, &size, sizeof(size));
156 write(keyd_fd, fingerprint->fp, size);
158 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
159 if (keybuf.size > 0) {
160 keybuf.buffer = malloc(keybuf.size);
162 logthing(LOGTHING_TRACE,
163 "Getting %d bytes of key data.",
165 while (bytes >= 0 && count < keybuf.size) {
166 bytes = read(keyd_fd, &keybuf.buffer[count],
167 keybuf.size - count);
168 logthing(LOGTHING_TRACE,
169 "Read %d bytes.", bytes);
172 read_openpgp_stream(buffer_fetchchar, &keybuf,
174 parse_keys(packets, publickey);
175 free_packet_list(packets);
178 keybuf.buffer = NULL;
183 return (count > 0) ? 1 : 0;
187 * delete_key - Given a keyid delete the key from storage.
188 * @keyid: The keyid to delete.
189 * @intrans: If we're already in a transaction.
191 * This function deletes a public key from whatever storage mechanism we
192 * are using. Returns 0 if the key existed.
194 static int keyd_delete_key(struct onak_dbctx *dbctx,
195 uint64_t keyid, bool intrans)
197 int keyd_fd = (intptr_t) dbctx->priv;
199 if (keyd_send_cmd(keyd_fd, KEYD_CMD_DELETE)) {
200 write(keyd_fd, &keyid, sizeof(keyid));
207 * store_key - Takes a key and stores it.
208 * @publickey: A pointer to the public key to store.
209 * @intrans: If we're already in a transaction.
210 * @update: If true the key exists and should be updated.
212 * This function stores a public key in whatever storage mechanism we are
213 * using. intrans indicates if we're already in a transaction so don't
214 * need to start one. update indicates if the key already exists and is
215 * just being updated.
217 * TODO: Do we store multiple keys of the same id? Or only one and replace
220 static int keyd_store_key(struct onak_dbctx *dbctx,
221 struct openpgp_publickey *publickey, bool intrans,
224 int keyd_fd = (intptr_t) dbctx->priv;
225 struct buffer_ctx keybuf;
226 struct openpgp_packet_list *packets = NULL;
227 struct openpgp_packet_list *list_end = NULL;
228 struct openpgp_publickey *next = NULL;
231 if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
232 logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
237 keyd_delete_key(dbctx, keyid, false);
240 if (keyd_send_cmd(keyd_fd, KEYD_CMD_STORE)) {
243 keybuf.buffer = malloc(keybuf.size);
245 next = publickey->next;
246 publickey->next = NULL;
247 flatten_publickey(publickey,
250 publickey->next = next;
252 write_openpgp_stream(buffer_putchar, &keybuf, packets);
253 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
254 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
255 write(keyd_fd, keybuf.buffer, keybuf.offset);
257 free_packet_list(packets);
258 packets = list_end = NULL;
260 keybuf.buffer = NULL;
261 keybuf.size = keybuf.offset = 0;
268 * fetch_key_text - Trys to find the keys that contain the supplied text.
269 * @search: The text to search for.
270 * @publickey: A pointer to a structure to return the key in.
272 * This function searches for the supplied text and returns the keys that
275 static int keyd_fetch_key_text(struct onak_dbctx *dbctx,
277 struct openpgp_publickey **publickey)
279 int keyd_fd = (intptr_t) dbctx->priv;
280 struct buffer_ctx keybuf;
281 struct openpgp_packet_list *packets = NULL;
285 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_TEXT)) {
286 bytes = strlen(search);
287 write(keyd_fd, &bytes, sizeof(bytes));
288 write(keyd_fd, search, bytes);
290 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
291 if (keybuf.size > 0) {
292 keybuf.buffer = malloc(keybuf.size);
294 logthing(LOGTHING_TRACE,
295 "Getting %d bytes of key data.",
297 while (bytes >= 0 && count < keybuf.size) {
298 bytes = read(keyd_fd, &keybuf.buffer[count],
299 keybuf.size - count);
300 logthing(LOGTHING_TRACE,
301 "Read %d bytes.", bytes);
304 read_openpgp_stream(buffer_fetchchar, &keybuf,
306 parse_keys(packets, publickey);
307 free_packet_list(packets);
310 keybuf.buffer = NULL;
315 return (count > 0) ? 1 : 0;
320 static int keyd_fetch_key_skshash(struct onak_dbctx *dbctx,
321 const struct skshash *hash,
322 struct openpgp_publickey **publickey)
324 int keyd_fd = (intptr_t) dbctx->priv;
325 struct buffer_ctx keybuf;
326 struct openpgp_packet_list *packets = NULL;
330 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_SKSHASH)) {
331 write(keyd_fd, hash->hash, sizeof(hash->hash));
333 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
334 if (keybuf.size > 0) {
335 keybuf.buffer = malloc(keybuf.size);
337 logthing(LOGTHING_TRACE,
338 "Getting %d bytes of key data.",
340 while (bytes >= 0 && count < keybuf.size) {
341 bytes = read(keyd_fd, &keybuf.buffer[count],
342 keybuf.size - count);
343 logthing(LOGTHING_TRACE,
344 "Read %d bytes.", bytes);
347 read_openpgp_stream(buffer_fetchchar, &keybuf,
349 parse_keys(packets, publickey);
350 free_packet_list(packets);
353 keybuf.buffer = NULL;
358 return (count > 0) ? 1 : 0;
363 * getfullkeyid - Maps a 32bit key id to a 64bit one.
364 * @keyid: The 32bit keyid.
366 * This function maps a 32bit key id to the full 64bit one. It returns the
367 * full keyid. If the key isn't found a keyid of 0 is returned.
369 static uint64_t keyd_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
371 int keyd_fd = (intptr_t) dbctx->priv;
372 uint32_t cmd = KEYD_CMD_GETFULLKEYID;
374 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GETFULLKEYID)) {
375 write(keyd_fd, &keyid, sizeof(keyid));
376 read(keyd_fd, &cmd, sizeof(cmd));
377 if (cmd != sizeof(keyid)) {
380 read(keyd_fd, &keyid, sizeof(keyid));
387 * iterate_keys - call a function once for each key in the db.
388 * @iterfunc: The function to call.
389 * @ctx: A context pointer
391 * Calls iterfunc once for each key in the database. ctx is passed
392 * unaltered to iterfunc. This function is intended to aid database dumps
393 * and statistic calculations.
395 * Returns the number of keys we iterated over.
397 static int keyd_iterate_keys(struct onak_dbctx *dbctx,
398 void (*iterfunc)(void *ctx,
399 struct openpgp_publickey *key), void *ctx)
401 int keyd_fd = (intptr_t) dbctx->priv;
402 struct buffer_ctx keybuf;
403 struct openpgp_packet_list *packets = NULL;
404 struct openpgp_publickey *key = NULL;
409 if (keyd_send_cmd(keyd_fd, KEYD_CMD_KEYITER)) {
411 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
412 while (keybuf.size > 0) {
413 keybuf.buffer = malloc(keybuf.size);
415 logthing(LOGTHING_TRACE,
416 "Getting %d bytes of key data.",
418 while (bytes >= 0 && count < keybuf.size) {
419 bytes = read(keyd_fd, &keybuf.buffer[count],
420 keybuf.size - count);
421 logthing(LOGTHING_TRACE,
422 "Read %d bytes.", bytes);
425 read_openpgp_stream(buffer_fetchchar, &keybuf,
427 parse_keys(packets, &key);
429 if (iterfunc != NULL && key != NULL) {
435 free_packet_list(packets);
438 keybuf.buffer = NULL;
439 keybuf.size = keybuf.offset = 0;
443 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
450 #define NEED_KEYID2UID 1
451 #define NEED_GETKEYSIGS 1
452 #define NEED_UPDATEKEYS 1
456 * cleanupdb - De-initialize the key database.
458 * This function should be called upon program exit to allow the DB to
459 * cleanup after itself.
461 static void keyd_cleanupdb(struct onak_dbctx *dbctx)
463 int keyd_fd = (intptr_t) dbctx->priv;
464 uint32_t cmd = KEYD_CMD_CLOSE;
466 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
467 logthing(LOGTHING_CRITICAL,
468 "Couldn't send close cmd: %s (%d)",
473 if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
474 logthing(LOGTHING_CRITICAL,
475 "Couldn't read close cmd reply: %s (%d)",
478 } else if (cmd != KEYD_REPLY_OK) {
479 logthing(LOGTHING_CRITICAL,
480 "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
483 if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
484 logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
487 if (close(keyd_fd) < 0) {
488 logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
498 * initdb - Initialize the key database.
499 * @readonly: If we'll only be reading the DB, not writing to it.
501 * This function should be called before any of the other functions in
502 * this file are called in order to allow the DB to be initialized ready
505 struct onak_dbctx *keydb_keyd_init(bool readonly)
507 struct sockaddr_un sock;
508 uint32_t cmd = KEYD_CMD_UNKNOWN;
509 uint32_t reply = KEYD_REPLY_UNKNOWN_CMD;
512 struct onak_dbctx *dbctx;
514 dbctx = malloc(sizeof(*dbctx));
519 keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
521 logthing(LOGTHING_CRITICAL,
522 "Couldn't open socket: %s (%d)",
528 sock.sun_family = AF_UNIX;
529 snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
532 if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
533 logthing(LOGTHING_CRITICAL,
534 "Couldn't connect to socket %s: %s (%d)",
541 cmd = KEYD_CMD_VERSION;
542 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
543 logthing(LOGTHING_CRITICAL,
544 "Couldn't write version cmd: %s (%d)",
548 count = read(keyd_fd, &reply, sizeof(reply));
549 if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
550 count = read(keyd_fd, &reply, sizeof(reply));
551 if (count != sizeof(reply) || reply != sizeof(reply)) {
552 logthing(LOGTHING_CRITICAL,
553 "Error! Unexpected keyd version "
555 reply, sizeof(reply));
559 count = read(keyd_fd, &reply, sizeof(reply));
560 if (count != sizeof(reply)) {
561 logthing(LOGTHING_CRITICAL,
562 "Error! Unexpected keyd version "
564 count, sizeof(reply));
567 logthing(LOGTHING_DEBUG,
568 "keyd protocol version %d",
570 if (reply != keyd_version) {
571 logthing(LOGTHING_CRITICAL,
572 "Error! keyd protocol version "
573 "mismatch. (us = %d, it = %d)",
574 keyd_version, reply);
579 dbctx->priv = (void *) (intptr_t) keyd_fd;
580 dbctx->cleanupdb = keyd_cleanupdb;
581 dbctx->starttrans = keyd_starttrans;
582 dbctx->endtrans = keyd_endtrans;
583 dbctx->fetch_key_id = keyd_fetch_key_id;
584 dbctx->fetch_key_fp = keyd_fetch_key_fp;
585 dbctx->fetch_key_text = keyd_fetch_key_text;
586 dbctx->fetch_key_skshash = keyd_fetch_key_skshash;
587 dbctx->store_key = keyd_store_key;
588 dbctx->update_keys = generic_update_keys;
589 dbctx->delete_key = keyd_delete_key;
590 dbctx->getkeysigs = generic_getkeysigs;
591 dbctx->cached_getkeysigs = generic_cached_getkeysigs;
592 dbctx->keyid2uid = generic_keyid2uid;
593 dbctx->getfullkeyid = keyd_getfullkeyid;
594 dbctx->iterate_keys = keyd_iterate_keys;