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.
27 #include <sys/socket.h>
28 #include <sys/types.h>
32 #include "charfuncs.h"
36 #include "keystructs.h"
40 #include "onak-conf.h"
44 * starttrans - Start a transaction.
46 * Start a transaction. Intended to be used if we're about to perform many
47 * operations on the database to help speed it all up, or if we want
48 * something to only succeed if all relevant operations are successful.
50 static bool keyd_starttrans(struct onak_dbctx *dbctx)
56 * endtrans - End a transaction.
60 static void keyd_endtrans(struct onak_dbctx *dbctx)
65 static bool keyd_send_cmd(int fd, enum keyd_ops _cmd)
70 bytes = write(fd, &cmd, sizeof(cmd));
71 if (bytes != sizeof(cmd)) {
75 bytes = read(fd, &cmd, sizeof(cmd));
76 if (bytes != sizeof(cmd)) {
80 if (cmd != KEYD_REPLY_OK) {
88 * fetch_key - Given a keyid fetch the key from storage.
89 * @keyid: The keyid to fetch.
90 * @publickey: A pointer to a structure to return the key in.
91 * @intrans: If we're already in a transaction.
93 * This function returns a public key from whatever storage mechanism we
96 * TODO: What about keyid collisions? Should we use fingerprint instead?
98 static int keyd_fetch_key_id(struct onak_dbctx *dbctx,
100 struct openpgp_publickey **publickey,
103 int keyd_fd = (intptr_t) dbctx->priv;
104 struct buffer_ctx keybuf;
105 struct openpgp_packet_list *packets = NULL;
109 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_ID)) {
110 write(keyd_fd, &keyid, sizeof(keyid));
112 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
113 if (keybuf.size > 0) {
114 keybuf.buffer = malloc(keybuf.size);
116 logthing(LOGTHING_TRACE,
117 "Getting %d bytes of key data.",
119 while (bytes >= 0 && count < keybuf.size) {
120 bytes = read(keyd_fd, &keybuf.buffer[count],
121 keybuf.size - count);
122 logthing(LOGTHING_TRACE,
123 "Read %d bytes.", bytes);
126 read_openpgp_stream(buffer_fetchchar, &keybuf,
128 parse_keys(packets, publickey);
129 free_packet_list(packets);
132 keybuf.buffer = NULL;
137 return (count > 0) ? 1 : 0;
140 static int keyd_fetch_key_fp(struct onak_dbctx *dbctx,
141 struct openpgp_fingerprint *fingerprint,
142 struct openpgp_publickey **publickey,
145 int keyd_fd = (intptr_t) dbctx->priv;
146 struct buffer_ctx keybuf;
147 struct openpgp_packet_list *packets = NULL;
152 if (fingerprint->length > MAX_FINGERPRINT_LEN) {
156 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_FP)) {
157 size = fingerprint->length;
158 write(keyd_fd, &size, sizeof(size));
159 write(keyd_fd, fingerprint->fp, size);
161 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
162 if (keybuf.size > 0) {
163 keybuf.buffer = malloc(keybuf.size);
165 logthing(LOGTHING_TRACE,
166 "Getting %d bytes of key data.",
168 while (bytes >= 0 && count < keybuf.size) {
169 bytes = read(keyd_fd, &keybuf.buffer[count],
170 keybuf.size - count);
171 logthing(LOGTHING_TRACE,
172 "Read %d bytes.", bytes);
175 read_openpgp_stream(buffer_fetchchar, &keybuf,
177 parse_keys(packets, publickey);
178 free_packet_list(packets);
181 keybuf.buffer = NULL;
186 return (count > 0) ? 1 : 0;
190 * delete_key - Given a keyid delete the key from storage.
191 * @keyid: The keyid to delete.
192 * @intrans: If we're already in a transaction.
194 * This function deletes a public key from whatever storage mechanism we
195 * are using. Returns 0 if the key existed.
197 static int keyd_delete_key(struct onak_dbctx *dbctx,
198 uint64_t keyid, bool intrans)
200 int keyd_fd = (intptr_t) dbctx->priv;
202 if (keyd_send_cmd(keyd_fd, KEYD_CMD_DELETE)) {
203 write(keyd_fd, &keyid, sizeof(keyid));
210 * store_key - Takes a key and stores it.
211 * @publickey: A pointer to the public key to store.
212 * @intrans: If we're already in a transaction.
213 * @update: If true the key exists and should be updated.
215 * This function stores a public key in whatever storage mechanism we are
216 * using. intrans indicates if we're already in a transaction so don't
217 * need to start one. update indicates if the key already exists and is
218 * just being updated.
220 * TODO: Do we store multiple keys of the same id? Or only one and replace
223 static int keyd_store_key(struct onak_dbctx *dbctx,
224 struct openpgp_publickey *publickey, bool intrans,
227 int keyd_fd = (intptr_t) dbctx->priv;
228 struct buffer_ctx keybuf;
229 struct openpgp_packet_list *packets = NULL;
230 struct openpgp_packet_list *list_end = NULL;
231 struct openpgp_publickey *next = NULL;
233 enum keyd_ops cmd = KEYD_CMD_STORE;
235 if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
236 logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
241 cmd = KEYD_CMD_UPDATE;
244 if (keyd_send_cmd(keyd_fd, cmd)) {
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(struct onak_dbctx *dbctx,
281 struct openpgp_publickey **publickey)
283 int keyd_fd = (intptr_t) dbctx->priv;
284 struct buffer_ctx keybuf;
285 struct openpgp_packet_list *packets = NULL;
289 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_TEXT)) {
290 bytes = strlen(search);
291 write(keyd_fd, &bytes, sizeof(bytes));
292 write(keyd_fd, search, bytes);
294 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
295 if (keybuf.size > 0) {
296 keybuf.buffer = malloc(keybuf.size);
298 logthing(LOGTHING_TRACE,
299 "Getting %d bytes of key data.",
301 while (bytes >= 0 && count < keybuf.size) {
302 bytes = read(keyd_fd, &keybuf.buffer[count],
303 keybuf.size - count);
304 logthing(LOGTHING_TRACE,
305 "Read %d bytes.", bytes);
308 read_openpgp_stream(buffer_fetchchar, &keybuf,
310 parse_keys(packets, publickey);
311 free_packet_list(packets);
314 keybuf.buffer = NULL;
319 return (count > 0) ? 1 : 0;
324 static int keyd_fetch_key_skshash(struct onak_dbctx *dbctx,
325 const struct skshash *hash,
326 struct openpgp_publickey **publickey)
328 int keyd_fd = (intptr_t) dbctx->priv;
329 struct buffer_ctx keybuf;
330 struct openpgp_packet_list *packets = NULL;
334 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_SKSHASH)) {
335 write(keyd_fd, hash->hash, sizeof(hash->hash));
337 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
338 if (keybuf.size > 0) {
339 keybuf.buffer = malloc(keybuf.size);
341 logthing(LOGTHING_TRACE,
342 "Getting %d bytes of key data.",
344 while (bytes >= 0 && count < keybuf.size) {
345 bytes = read(keyd_fd, &keybuf.buffer[count],
346 keybuf.size - count);
347 logthing(LOGTHING_TRACE,
348 "Read %d bytes.", bytes);
351 read_openpgp_stream(buffer_fetchchar, &keybuf,
353 parse_keys(packets, publickey);
354 free_packet_list(packets);
357 keybuf.buffer = NULL;
362 return (count > 0) ? 1 : 0;
367 * getfullkeyid - Maps a 32bit key id to a 64bit one.
368 * @keyid: The 32bit keyid.
370 * This function maps a 32bit key id to the full 64bit one. It returns the
371 * full keyid. If the key isn't found a keyid of 0 is returned.
373 static uint64_t keyd_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
375 int keyd_fd = (intptr_t) dbctx->priv;
376 uint32_t cmd = KEYD_CMD_GETFULLKEYID;
378 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GETFULLKEYID)) {
379 write(keyd_fd, &keyid, sizeof(keyid));
380 read(keyd_fd, &cmd, sizeof(cmd));
381 if (cmd != sizeof(keyid)) {
384 read(keyd_fd, &keyid, sizeof(keyid));
391 * iterate_keys - call a function once for each key in the db.
392 * @iterfunc: The function to call.
393 * @ctx: A context pointer
395 * Calls iterfunc once for each key in the database. ctx is passed
396 * unaltered to iterfunc. This function is intended to aid database dumps
397 * and statistic calculations.
399 * Returns the number of keys we iterated over.
401 static int keyd_iterate_keys(struct onak_dbctx *dbctx,
402 void (*iterfunc)(void *ctx,
403 struct openpgp_publickey *key), void *ctx)
405 int keyd_fd = (intptr_t) dbctx->priv;
406 struct buffer_ctx keybuf;
407 struct openpgp_packet_list *packets = NULL;
408 struct openpgp_publickey *key = NULL;
413 if (keyd_send_cmd(keyd_fd, KEYD_CMD_KEYITER)) {
415 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
416 while (keybuf.size > 0) {
417 keybuf.buffer = malloc(keybuf.size);
419 logthing(LOGTHING_TRACE,
420 "Getting %d bytes of key data.",
422 while (bytes >= 0 && count < keybuf.size) {
423 bytes = read(keyd_fd, &keybuf.buffer[count],
424 keybuf.size - count);
425 logthing(LOGTHING_TRACE,
426 "Read %d bytes.", bytes);
429 read_openpgp_stream(buffer_fetchchar, &keybuf,
431 parse_keys(packets, &key);
433 if (iterfunc != NULL && key != NULL) {
439 free_packet_list(packets);
442 keybuf.buffer = NULL;
443 keybuf.size = keybuf.offset = 0;
447 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
454 #define NEED_KEYID2UID 1
455 #define NEED_GETKEYSIGS 1
456 #define NEED_UPDATEKEYS 1
460 * cleanupdb - De-initialize the key database.
462 * This function should be called upon program exit to allow the DB to
463 * cleanup after itself.
465 static void keyd_cleanupdb(struct onak_dbctx *dbctx)
467 int keyd_fd = (intptr_t) dbctx->priv;
468 uint32_t cmd = KEYD_CMD_CLOSE;
470 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
471 logthing(LOGTHING_CRITICAL,
472 "Couldn't send close cmd: %s (%d)",
477 if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
478 logthing(LOGTHING_CRITICAL,
479 "Couldn't read close cmd reply: %s (%d)",
482 } else if (cmd != KEYD_REPLY_OK) {
483 logthing(LOGTHING_CRITICAL,
484 "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
487 if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
488 logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
491 if (close(keyd_fd) < 0) {
492 logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
502 * initdb - Initialize the key database.
503 * @readonly: If we'll only be reading the DB, not writing to it.
505 * This function should be called before any of the other functions in
506 * this file are called in order to allow the DB to be initialized ready
509 struct onak_dbctx *keydb_keyd_init(struct onak_db_config *dbcfg, bool readonly)
511 struct sockaddr_un sock;
512 uint32_t cmd = KEYD_CMD_UNKNOWN;
513 uint32_t reply = KEYD_REPLY_UNKNOWN_CMD;
516 struct onak_dbctx *dbctx;
518 dbctx = malloc(sizeof(*dbctx));
522 dbctx->config = dbcfg;
524 keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
526 logthing(LOGTHING_CRITICAL,
527 "Couldn't open socket: %s (%d)",
533 sock.sun_family = AF_UNIX;
534 snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
537 if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
538 logthing(LOGTHING_CRITICAL,
539 "Couldn't connect to socket %s: %s (%d)",
546 cmd = KEYD_CMD_VERSION;
547 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
548 logthing(LOGTHING_CRITICAL,
549 "Couldn't write version cmd: %s (%d)",
553 count = read(keyd_fd, &reply, sizeof(reply));
554 if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
555 count = read(keyd_fd, &reply, sizeof(reply));
556 if (count != sizeof(reply) || reply != sizeof(reply)) {
557 logthing(LOGTHING_CRITICAL,
558 "Error! Unexpected keyd version "
560 reply, sizeof(reply));
564 count = read(keyd_fd, &reply, sizeof(reply));
565 if (count != sizeof(reply)) {
566 logthing(LOGTHING_CRITICAL,
567 "Error! Unexpected keyd version "
569 count, sizeof(reply));
572 logthing(LOGTHING_DEBUG,
573 "keyd protocol version %d",
575 if (reply != keyd_version) {
576 logthing(LOGTHING_CRITICAL,
577 "Error! keyd protocol version "
578 "mismatch. (us = %d, it = %d)",
579 keyd_version, reply);
584 dbctx->priv = (void *) (intptr_t) keyd_fd;
585 dbctx->cleanupdb = keyd_cleanupdb;
586 dbctx->starttrans = keyd_starttrans;
587 dbctx->endtrans = keyd_endtrans;
588 dbctx->fetch_key_id = keyd_fetch_key_id;
589 dbctx->fetch_key_fp = keyd_fetch_key_fp;
590 dbctx->fetch_key_text = keyd_fetch_key_text;
591 dbctx->fetch_key_skshash = keyd_fetch_key_skshash;
592 dbctx->store_key = keyd_store_key;
593 dbctx->update_keys = generic_update_keys;
594 dbctx->delete_key = keyd_delete_key;
595 dbctx->getkeysigs = generic_getkeysigs;
596 dbctx->cached_getkeysigs = generic_cached_getkeysigs;
597 dbctx->keyid2uid = generic_keyid2uid;
598 dbctx->getfullkeyid = keyd_getfullkeyid;
599 dbctx->iterate_keys = keyd_iterate_keys;