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, see <https://www.gnu.org/licenses/>.
26 #include <sys/socket.h>
27 #include <sys/types.h>
31 #include "charfuncs.h"
35 #include "keystructs.h"
39 #include "onak-conf.h"
43 * starttrans - Start a transaction.
45 * Start a transaction. Intended to be used if we're about to perform many
46 * operations on the database to help speed it all up, or if we want
47 * something to only succeed if all relevant operations are successful.
49 static bool keyd_starttrans(struct onak_dbctx *dbctx)
55 * endtrans - End a transaction.
59 static void keyd_endtrans(struct onak_dbctx *dbctx)
64 static bool keyd_send_cmd(int fd, enum keyd_ops _cmd)
69 bytes = write(fd, &cmd, sizeof(cmd));
70 if (bytes != sizeof(cmd)) {
74 bytes = read(fd, &cmd, sizeof(cmd));
75 if (bytes != sizeof(cmd)) {
79 if (cmd != KEYD_REPLY_OK) {
87 * fetch_key - Given a keyid fetch the key from storage.
88 * @keyid: The keyid to fetch.
89 * @publickey: A pointer to a structure to return the key in.
90 * @intrans: If we're already in a transaction.
92 * This function returns a public key from whatever storage mechanism we
95 static int keyd_fetch_key(struct onak_dbctx *dbctx,
96 struct openpgp_fingerprint *fingerprint,
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;
107 if (fingerprint->length > MAX_FINGERPRINT_LEN) {
111 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET)) {
112 size = fingerprint->length;
113 write(keyd_fd, &size, sizeof(size));
114 write(keyd_fd, fingerprint->fp, size);
116 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
117 if (keybuf.size > 0) {
118 keybuf.buffer = malloc(keybuf.size);
120 logthing(LOGTHING_TRACE,
121 "Getting %d bytes of key data.",
123 while (bytes >= 0 && count < keybuf.size) {
124 bytes = read(keyd_fd, &keybuf.buffer[count],
125 keybuf.size - count);
126 logthing(LOGTHING_TRACE,
127 "Read %d bytes.", bytes);
130 read_openpgp_stream(buffer_fetchchar, &keybuf,
132 parse_keys(packets, publickey);
133 free_packet_list(packets);
136 keybuf.buffer = NULL;
141 return (count > 0) ? 1 : 0;
144 static int keyd_fetch_key_fp(struct onak_dbctx *dbctx,
145 struct openpgp_fingerprint *fingerprint,
146 struct openpgp_publickey **publickey,
149 int keyd_fd = (intptr_t) dbctx->priv;
150 struct buffer_ctx keybuf;
151 struct openpgp_packet_list *packets = NULL;
156 if (fingerprint->length > MAX_FINGERPRINT_LEN) {
160 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_FP)) {
161 size = fingerprint->length;
162 write(keyd_fd, &size, sizeof(size));
163 write(keyd_fd, fingerprint->fp, size);
165 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
166 if (keybuf.size > 0) {
167 keybuf.buffer = malloc(keybuf.size);
169 logthing(LOGTHING_TRACE,
170 "Getting %d bytes of key data.",
172 while (bytes >= 0 && count < keybuf.size) {
173 bytes = read(keyd_fd, &keybuf.buffer[count],
174 keybuf.size - count);
175 logthing(LOGTHING_TRACE,
176 "Read %d bytes.", bytes);
179 read_openpgp_stream(buffer_fetchchar, &keybuf,
181 parse_keys(packets, publickey);
182 free_packet_list(packets);
185 keybuf.buffer = NULL;
190 return (count > 0) ? 1 : 0;
193 static int keyd_fetch_key_id(struct onak_dbctx *dbctx,
195 struct openpgp_publickey **publickey,
198 int keyd_fd = (intptr_t) dbctx->priv;
199 struct buffer_ctx keybuf;
200 struct openpgp_packet_list *packets = NULL;
204 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_ID)) {
205 write(keyd_fd, &keyid, sizeof(keyid));
207 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
208 if (keybuf.size > 0) {
209 keybuf.buffer = malloc(keybuf.size);
211 logthing(LOGTHING_TRACE,
212 "Getting %d bytes of key data.",
214 while (bytes >= 0 && count < keybuf.size) {
215 bytes = read(keyd_fd, &keybuf.buffer[count],
216 keybuf.size - count);
217 logthing(LOGTHING_TRACE,
218 "Read %d bytes.", bytes);
221 read_openpgp_stream(buffer_fetchchar, &keybuf,
223 parse_keys(packets, publickey);
224 free_packet_list(packets);
227 keybuf.buffer = NULL;
232 return (count > 0) ? 1 : 0;
236 * delete_key - Given a keyid delete the key from storage.
237 * @fp: The fingerprint of the key to delete.
238 * @intrans: If we're already in a transaction.
240 * This function deletes a public key from whatever storage mechanism we
241 * are using. Returns 0 if the key existed.
243 static int keyd_delete_key(struct onak_dbctx *dbctx,
244 struct openpgp_fingerprint *fp, bool intrans)
246 int keyd_fd = (intptr_t) dbctx->priv;
248 if (keyd_send_cmd(keyd_fd, KEYD_CMD_DELETE)) {
249 write(keyd_fd, fp, sizeof(*fp));
256 * store_key - Takes a key and stores it.
257 * @publickey: A pointer to the public key to store.
258 * @intrans: If we're already in a transaction.
259 * @update: If true the key exists and should be updated.
261 * This function stores a public key in whatever storage mechanism we are
262 * using. intrans indicates if we're already in a transaction so don't
263 * need to start one. update indicates if the key already exists and is
264 * just being updated.
266 * TODO: Do we store multiple keys of the same id? Or only one and replace
269 static int keyd_store_key(struct onak_dbctx *dbctx,
270 struct openpgp_publickey *publickey, bool intrans,
273 int keyd_fd = (intptr_t) dbctx->priv;
274 struct buffer_ctx keybuf;
275 struct openpgp_packet_list *packets = NULL;
276 struct openpgp_packet_list *list_end = NULL;
277 struct openpgp_publickey *next = NULL;
279 enum keyd_ops cmd = KEYD_CMD_STORE;
281 if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
282 logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
287 cmd = KEYD_CMD_UPDATE;
290 if (keyd_send_cmd(keyd_fd, cmd)) {
293 keybuf.buffer = malloc(keybuf.size);
295 next = publickey->next;
296 publickey->next = NULL;
297 flatten_publickey(publickey,
300 publickey->next = next;
302 write_openpgp_stream(buffer_putchar, &keybuf, packets);
303 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
304 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
305 write(keyd_fd, keybuf.buffer, keybuf.offset);
307 free_packet_list(packets);
308 packets = list_end = NULL;
310 keybuf.buffer = NULL;
311 keybuf.size = keybuf.offset = 0;
318 * fetch_key_text - Trys to find the keys that contain the supplied text.
319 * @search: The text to search for.
320 * @publickey: A pointer to a structure to return the key in.
322 * This function searches for the supplied text and returns the keys that
325 static int keyd_fetch_key_text(struct onak_dbctx *dbctx,
327 struct openpgp_publickey **publickey)
329 int keyd_fd = (intptr_t) dbctx->priv;
330 struct buffer_ctx keybuf;
331 struct openpgp_packet_list *packets = NULL;
335 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_TEXT)) {
336 bytes = strlen(search);
337 write(keyd_fd, &bytes, sizeof(bytes));
338 write(keyd_fd, search, bytes);
340 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
341 if (keybuf.size > 0) {
342 keybuf.buffer = malloc(keybuf.size);
344 logthing(LOGTHING_TRACE,
345 "Getting %d bytes of key data.",
347 while (bytes >= 0 && count < keybuf.size) {
348 bytes = read(keyd_fd, &keybuf.buffer[count],
349 keybuf.size - count);
350 logthing(LOGTHING_TRACE,
351 "Read %d bytes.", bytes);
354 read_openpgp_stream(buffer_fetchchar, &keybuf,
356 parse_keys(packets, publickey);
357 free_packet_list(packets);
360 keybuf.buffer = NULL;
365 return (count > 0) ? 1 : 0;
370 static int keyd_fetch_key_skshash(struct onak_dbctx *dbctx,
371 const struct skshash *hash,
372 struct openpgp_publickey **publickey)
374 int keyd_fd = (intptr_t) dbctx->priv;
375 struct buffer_ctx keybuf;
376 struct openpgp_packet_list *packets = NULL;
380 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_SKSHASH)) {
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;
412 * iterate_keys - call a function once for each key in the db.
413 * @iterfunc: The function to call.
414 * @ctx: A context pointer
416 * Calls iterfunc once for each key in the database. ctx is passed
417 * unaltered to iterfunc. This function is intended to aid database dumps
418 * and statistic calculations.
420 * Returns the number of keys we iterated over.
422 static int keyd_iterate_keys(struct onak_dbctx *dbctx,
423 void (*iterfunc)(void *ctx,
424 struct openpgp_publickey *key), void *ctx)
426 int keyd_fd = (intptr_t) dbctx->priv;
427 struct buffer_ctx keybuf;
428 struct openpgp_packet_list *packets = NULL;
429 struct openpgp_publickey *key = NULL;
434 if (keyd_send_cmd(keyd_fd, KEYD_CMD_KEYITER)) {
436 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
437 while (keybuf.size > 0) {
438 keybuf.buffer = malloc(keybuf.size);
440 logthing(LOGTHING_TRACE,
441 "Getting %d bytes of key data.",
443 while (bytes >= 0 && count < keybuf.size) {
444 bytes = read(keyd_fd, &keybuf.buffer[count],
445 keybuf.size - count);
446 logthing(LOGTHING_TRACE,
447 "Read %d bytes.", bytes);
450 read_openpgp_stream(buffer_fetchchar, &keybuf,
452 parse_keys(packets, &key);
454 if (iterfunc != NULL && key != NULL) {
460 free_packet_list(packets);
463 keybuf.buffer = NULL;
464 keybuf.size = keybuf.offset = 0;
468 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
475 #define NEED_KEYID2UID 1
476 #define NEED_GETKEYSIGS 1
477 #define NEED_UPDATEKEYS 1
481 * cleanupdb - De-initialize the key database.
483 * This function should be called upon program exit to allow the DB to
484 * cleanup after itself.
486 static void keyd_cleanupdb(struct onak_dbctx *dbctx)
488 int keyd_fd = (intptr_t) dbctx->priv;
489 uint32_t cmd = KEYD_CMD_CLOSE;
491 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
492 logthing(LOGTHING_CRITICAL,
493 "Couldn't send close cmd: %s (%d)",
498 if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
499 logthing(LOGTHING_CRITICAL,
500 "Couldn't read close cmd reply: %s (%d)",
503 } else if (cmd != KEYD_REPLY_OK) {
504 logthing(LOGTHING_CRITICAL,
505 "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
508 if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
509 logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
512 if (close(keyd_fd) < 0) {
513 logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
523 * initdb - Initialize the key database.
524 * @readonly: If we'll only be reading the DB, not writing to it.
526 * This function should be called before any of the other functions in
527 * this file are called in order to allow the DB to be initialized ready
530 struct onak_dbctx *keydb_keyd_init(struct onak_db_config *dbcfg, bool readonly)
532 struct sockaddr_un sock;
533 uint32_t cmd = KEYD_CMD_UNKNOWN;
534 uint32_t reply = KEYD_REPLY_UNKNOWN_CMD;
537 struct onak_dbctx *dbctx;
539 dbctx = malloc(sizeof(*dbctx));
543 dbctx->config = dbcfg;
545 keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
547 logthing(LOGTHING_CRITICAL,
548 "Couldn't open socket: %s (%d)",
554 sock.sun_family = AF_UNIX;
555 snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
558 if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
559 logthing(LOGTHING_CRITICAL,
560 "Couldn't connect to socket %s: %s (%d)",
567 cmd = KEYD_CMD_VERSION;
568 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
569 logthing(LOGTHING_CRITICAL,
570 "Couldn't write version cmd: %s (%d)",
574 count = read(keyd_fd, &reply, sizeof(reply));
575 if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
576 count = read(keyd_fd, &reply, sizeof(reply));
577 if (count != sizeof(reply) || reply != sizeof(reply)) {
578 logthing(LOGTHING_CRITICAL,
579 "Error! Unexpected keyd version "
581 reply, sizeof(reply));
585 count = read(keyd_fd, &reply, sizeof(reply));
586 if (count != sizeof(reply)) {
587 logthing(LOGTHING_CRITICAL,
588 "Error! Unexpected keyd version "
590 count, sizeof(reply));
593 logthing(LOGTHING_DEBUG,
594 "keyd protocol version %d",
596 if (reply != keyd_version) {
597 logthing(LOGTHING_CRITICAL,
598 "Error! keyd protocol version "
599 "mismatch. (us = %d, it = %d)",
600 keyd_version, reply);
605 dbctx->priv = (void *) (intptr_t) keyd_fd;
606 dbctx->cleanupdb = keyd_cleanupdb;
607 dbctx->starttrans = keyd_starttrans;
608 dbctx->endtrans = keyd_endtrans;
609 dbctx->fetch_key = keyd_fetch_key;
610 dbctx->fetch_key_fp = keyd_fetch_key_fp;
611 dbctx->fetch_key_id = keyd_fetch_key_id;
612 dbctx->fetch_key_text = keyd_fetch_key_text;
613 dbctx->fetch_key_skshash = keyd_fetch_key_skshash;
614 dbctx->store_key = keyd_store_key;
615 dbctx->update_keys = generic_update_keys;
616 dbctx->delete_key = keyd_delete_key;
617 dbctx->getkeysigs = generic_getkeysigs;
618 dbctx->cached_getkeysigs = generic_cached_getkeysigs;
619 dbctx->keyid2uid = generic_keyid2uid;
620 dbctx->iterate_keys = keyd_iterate_keys;