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 "build-config.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(__unused struct onak_dbctx *dbctx)
56 * endtrans - End a transaction.
60 static void keyd_endtrans(__unused 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 static int keyd_fetch_key(struct onak_dbctx *dbctx,
97 struct openpgp_fingerprint *fingerprint,
98 struct openpgp_publickey **publickey,
99 __unused bool intrans)
101 int keyd_fd = (intptr_t) dbctx->priv;
102 struct buffer_ctx keybuf;
103 struct openpgp_packet_list *packets = NULL;
108 if (fingerprint->length > MAX_FINGERPRINT_LEN) {
112 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET)) {
113 size = fingerprint->length;
114 write(keyd_fd, &size, sizeof(size));
115 write(keyd_fd, fingerprint->fp, size);
117 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
118 if (keybuf.size > 0) {
119 keybuf.buffer = malloc(keybuf.size);
121 logthing(LOGTHING_TRACE,
122 "Getting %d bytes of key data.",
124 while (bytes >= 0 && count < keybuf.size) {
125 bytes = read(keyd_fd, &keybuf.buffer[count],
126 keybuf.size - count);
127 logthing(LOGTHING_TRACE,
128 "Read %d bytes.", bytes);
131 read_openpgp_stream(buffer_fetchchar, &keybuf,
133 parse_keys(packets, publickey);
134 free_packet_list(packets);
137 keybuf.buffer = NULL;
142 return (count > 0) ? 1 : 0;
145 static int keyd_fetch_key_fp(struct onak_dbctx *dbctx,
146 struct openpgp_fingerprint *fingerprint,
147 struct openpgp_publickey **publickey,
148 __unused bool intrans)
150 int keyd_fd = (intptr_t) dbctx->priv;
151 struct buffer_ctx keybuf;
152 struct openpgp_packet_list *packets = NULL;
157 if (fingerprint->length > MAX_FINGERPRINT_LEN) {
161 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_FP)) {
162 size = fingerprint->length;
163 write(keyd_fd, &size, sizeof(size));
164 write(keyd_fd, fingerprint->fp, size);
166 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
167 if (keybuf.size > 0) {
168 keybuf.buffer = malloc(keybuf.size);
170 logthing(LOGTHING_TRACE,
171 "Getting %d bytes of key data.",
173 while (bytes >= 0 && count < keybuf.size) {
174 bytes = read(keyd_fd, &keybuf.buffer[count],
175 keybuf.size - count);
176 logthing(LOGTHING_TRACE,
177 "Read %d bytes.", bytes);
180 read_openpgp_stream(buffer_fetchchar, &keybuf,
182 parse_keys(packets, publickey);
183 free_packet_list(packets);
186 keybuf.buffer = NULL;
191 return (count > 0) ? 1 : 0;
194 static int keyd_fetch_key_id(struct onak_dbctx *dbctx,
196 struct openpgp_publickey **publickey,
197 __unused bool intrans)
199 int keyd_fd = (intptr_t) dbctx->priv;
200 struct buffer_ctx keybuf;
201 struct openpgp_packet_list *packets = NULL;
205 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_ID)) {
206 write(keyd_fd, &keyid, sizeof(keyid));
208 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
209 if (keybuf.size > 0) {
210 keybuf.buffer = malloc(keybuf.size);
212 logthing(LOGTHING_TRACE,
213 "Getting %d bytes of key data.",
215 while (bytes >= 0 && count < keybuf.size) {
216 bytes = read(keyd_fd, &keybuf.buffer[count],
217 keybuf.size - count);
218 logthing(LOGTHING_TRACE,
219 "Read %d bytes.", bytes);
222 read_openpgp_stream(buffer_fetchchar, &keybuf,
224 parse_keys(packets, publickey);
225 free_packet_list(packets);
228 keybuf.buffer = NULL;
233 return (count > 0) ? 1 : 0;
237 * delete_key - Given a keyid delete the key from storage.
238 * @fp: The fingerprint of the key to delete.
239 * @intrans: If we're already in a transaction.
241 * This function deletes a public key from whatever storage mechanism we
242 * are using. Returns 0 if the key existed.
244 static int keyd_delete_key(struct onak_dbctx *dbctx,
245 struct openpgp_fingerprint *fp,
246 __unused bool intrans)
248 int keyd_fd = (intptr_t) dbctx->priv;
250 if (keyd_send_cmd(keyd_fd, KEYD_CMD_DELETE)) {
251 write(keyd_fd, fp, sizeof(*fp));
258 * store_key - Takes a key and stores it.
259 * @publickey: A pointer to the public key to store.
260 * @intrans: If we're already in a transaction.
261 * @update: If true the key exists and should be updated.
263 * This function stores a public key in whatever storage mechanism we are
264 * using. intrans indicates if we're already in a transaction so don't
265 * need to start one. update indicates if the key already exists and is
266 * just being updated.
268 * TODO: Do we store multiple keys of the same id? Or only one and replace
271 static int keyd_store_key(struct onak_dbctx *dbctx,
272 struct openpgp_publickey *publickey,
273 __unused bool intrans,
276 int keyd_fd = (intptr_t) dbctx->priv;
277 struct buffer_ctx keybuf;
278 struct openpgp_packet_list *packets = NULL;
279 struct openpgp_packet_list *list_end = NULL;
280 struct openpgp_publickey *next = NULL;
282 enum keyd_ops cmd = KEYD_CMD_STORE;
284 if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
285 logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
290 cmd = KEYD_CMD_UPDATE;
293 if (keyd_send_cmd(keyd_fd, cmd)) {
296 keybuf.buffer = malloc(keybuf.size);
298 next = publickey->next;
299 publickey->next = NULL;
300 flatten_publickey(publickey,
303 publickey->next = next;
305 write_openpgp_stream(buffer_putchar, &keybuf, packets);
306 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
307 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
308 write(keyd_fd, keybuf.buffer, keybuf.offset);
310 free_packet_list(packets);
311 packets = list_end = NULL;
313 keybuf.buffer = NULL;
314 keybuf.size = keybuf.offset = 0;
321 * fetch_key_text - Trys to find the keys that contain the supplied text.
322 * @search: The text to search for.
323 * @publickey: A pointer to a structure to return the key in.
325 * This function searches for the supplied text and returns the keys that
328 static int keyd_fetch_key_text(struct onak_dbctx *dbctx,
330 struct openpgp_publickey **publickey)
332 int keyd_fd = (intptr_t) dbctx->priv;
333 struct buffer_ctx keybuf;
334 struct openpgp_packet_list *packets = NULL;
338 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_TEXT)) {
339 bytes = strlen(search);
340 write(keyd_fd, &bytes, sizeof(bytes));
341 write(keyd_fd, search, bytes);
343 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
344 if (keybuf.size > 0) {
345 keybuf.buffer = malloc(keybuf.size);
347 logthing(LOGTHING_TRACE,
348 "Getting %d bytes of key data.",
350 while (bytes >= 0 && count < keybuf.size) {
351 bytes = read(keyd_fd, &keybuf.buffer[count],
352 keybuf.size - count);
353 logthing(LOGTHING_TRACE,
354 "Read %d bytes.", bytes);
357 read_openpgp_stream(buffer_fetchchar, &keybuf,
359 parse_keys(packets, publickey);
360 free_packet_list(packets);
363 keybuf.buffer = NULL;
368 return (count > 0) ? 1 : 0;
373 static int keyd_fetch_key_skshash(struct onak_dbctx *dbctx,
374 const struct skshash *hash,
375 struct openpgp_publickey **publickey)
377 int keyd_fd = (intptr_t) dbctx->priv;
378 struct buffer_ctx keybuf;
379 struct openpgp_packet_list *packets = NULL;
383 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_SKSHASH)) {
384 write(keyd_fd, hash->hash, sizeof(hash->hash));
386 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
387 if (keybuf.size > 0) {
388 keybuf.buffer = malloc(keybuf.size);
390 logthing(LOGTHING_TRACE,
391 "Getting %d bytes of key data.",
393 while (bytes >= 0 && count < keybuf.size) {
394 bytes = read(keyd_fd, &keybuf.buffer[count],
395 keybuf.size - count);
396 logthing(LOGTHING_TRACE,
397 "Read %d bytes.", bytes);
400 read_openpgp_stream(buffer_fetchchar, &keybuf,
402 parse_keys(packets, publickey);
403 free_packet_list(packets);
406 keybuf.buffer = NULL;
411 return (count > 0) ? 1 : 0;
415 * iterate_keys - call a function once for each key in the db.
416 * @iterfunc: The function to call.
417 * @ctx: A context pointer
419 * Calls iterfunc once for each key in the database. ctx is passed
420 * unaltered to iterfunc. This function is intended to aid database dumps
421 * and statistic calculations.
423 * Returns the number of keys we iterated over.
425 static int keyd_iterate_keys(struct onak_dbctx *dbctx,
426 void (*iterfunc)(void *ctx,
427 struct openpgp_publickey *key), void *ctx)
429 int keyd_fd = (intptr_t) dbctx->priv;
430 struct buffer_ctx keybuf;
431 struct openpgp_packet_list *packets = NULL;
432 struct openpgp_publickey *key = NULL;
437 if (keyd_send_cmd(keyd_fd, KEYD_CMD_KEYITER)) {
439 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
440 while (keybuf.size > 0) {
441 keybuf.buffer = malloc(keybuf.size);
443 logthing(LOGTHING_TRACE,
444 "Getting %d bytes of key data.",
446 while (bytes >= 0 && count < keybuf.size) {
447 bytes = read(keyd_fd, &keybuf.buffer[count],
448 keybuf.size - count);
449 logthing(LOGTHING_TRACE,
450 "Read %d bytes.", bytes);
453 read_openpgp_stream(buffer_fetchchar, &keybuf,
455 parse_keys(packets, &key);
457 if (iterfunc != NULL && key != NULL) {
463 free_packet_list(packets);
466 keybuf.buffer = NULL;
467 keybuf.size = keybuf.offset = 0;
471 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
478 #define NEED_KEYID2UID 1
479 #define NEED_GETKEYSIGS 1
480 #define NEED_UPDATEKEYS 1
484 * cleanupdb - De-initialize the key database.
486 * This function should be called upon program exit to allow the DB to
487 * cleanup after itself.
489 static void keyd_cleanupdb(struct onak_dbctx *dbctx)
491 int keyd_fd = (intptr_t) dbctx->priv;
492 uint32_t cmd = KEYD_CMD_CLOSE;
494 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
495 logthing(LOGTHING_CRITICAL,
496 "Couldn't send close cmd: %s (%d)",
501 if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
502 logthing(LOGTHING_CRITICAL,
503 "Couldn't read close cmd reply: %s (%d)",
506 } else if (cmd != KEYD_REPLY_OK) {
507 logthing(LOGTHING_CRITICAL,
508 "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
511 if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
512 logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
515 if (close(keyd_fd) < 0) {
516 logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
526 * initdb - Initialize the key database.
527 * @readonly: If we'll only be reading the DB, not writing to it.
529 * This function should be called before any of the other functions in
530 * this file are called in order to allow the DB to be initialized ready
533 struct onak_dbctx *keydb_keyd_init(struct onak_db_config *dbcfg,
534 __unused bool readonly)
536 struct sockaddr_un sock;
537 uint32_t cmd = KEYD_CMD_UNKNOWN;
538 uint32_t reply = KEYD_REPLY_UNKNOWN_CMD;
541 struct onak_dbctx *dbctx;
543 dbctx = malloc(sizeof(*dbctx));
547 dbctx->config = dbcfg;
549 keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
551 logthing(LOGTHING_CRITICAL,
552 "Couldn't open socket: %s (%d)",
558 sock.sun_family = AF_UNIX;
559 snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
562 if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
563 logthing(LOGTHING_CRITICAL,
564 "Couldn't connect to socket %s: %s (%d)",
571 cmd = KEYD_CMD_VERSION;
572 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
573 logthing(LOGTHING_CRITICAL,
574 "Couldn't write version cmd: %s (%d)",
578 count = read(keyd_fd, &reply, sizeof(reply));
579 if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
580 count = read(keyd_fd, &reply, sizeof(reply));
581 if (count != sizeof(reply) || reply != sizeof(reply)) {
582 logthing(LOGTHING_CRITICAL,
583 "Error! Unexpected keyd version "
585 reply, sizeof(reply));
589 count = read(keyd_fd, &reply, sizeof(reply));
590 if (count != sizeof(reply)) {
591 logthing(LOGTHING_CRITICAL,
592 "Error! Unexpected keyd version "
594 count, sizeof(reply));
597 logthing(LOGTHING_DEBUG,
598 "keyd protocol version %d",
600 if (reply != keyd_version) {
601 logthing(LOGTHING_CRITICAL,
602 "Error! keyd protocol version "
603 "mismatch. (us = %d, it = %d)",
604 keyd_version, reply);
609 dbctx->priv = (void *) (intptr_t) keyd_fd;
610 dbctx->cleanupdb = keyd_cleanupdb;
611 dbctx->starttrans = keyd_starttrans;
612 dbctx->endtrans = keyd_endtrans;
613 dbctx->fetch_key = keyd_fetch_key;
614 dbctx->fetch_key_fp = keyd_fetch_key_fp;
615 dbctx->fetch_key_id = keyd_fetch_key_id;
616 dbctx->fetch_key_text = keyd_fetch_key_text;
617 dbctx->fetch_key_skshash = keyd_fetch_key_skshash;
618 dbctx->store_key = keyd_store_key;
619 dbctx->update_keys = generic_update_keys;
620 dbctx->delete_key = keyd_delete_key;
621 dbctx->getkeysigs = generic_getkeysigs;
622 dbctx->cached_getkeysigs = generic_cached_getkeysigs;
623 dbctx->keyid2uid = generic_keyid2uid;
624 dbctx->iterate_keys = keyd_iterate_keys;