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 * TODO: What about keyid collisions? Should we use fingerprint instead?
97 static int keyd_fetch_key_id(struct onak_dbctx *dbctx,
99 struct openpgp_publickey **publickey,
102 int keyd_fd = (intptr_t) dbctx->priv;
103 struct buffer_ctx keybuf;
104 struct openpgp_packet_list *packets = NULL;
108 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_ID)) {
109 write(keyd_fd, &keyid, sizeof(keyid));
111 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
112 if (keybuf.size > 0) {
113 keybuf.buffer = malloc(keybuf.size);
115 logthing(LOGTHING_TRACE,
116 "Getting %d bytes of key data.",
118 while (bytes >= 0 && count < keybuf.size) {
119 bytes = read(keyd_fd, &keybuf.buffer[count],
120 keybuf.size - count);
121 logthing(LOGTHING_TRACE,
122 "Read %d bytes.", bytes);
125 read_openpgp_stream(buffer_fetchchar, &keybuf,
127 parse_keys(packets, publickey);
128 free_packet_list(packets);
131 keybuf.buffer = NULL;
136 return (count > 0) ? 1 : 0;
139 static int keyd_fetch_key_fp(struct onak_dbctx *dbctx,
140 struct openpgp_fingerprint *fingerprint,
141 struct openpgp_publickey **publickey,
144 int keyd_fd = (intptr_t) dbctx->priv;
145 struct buffer_ctx keybuf;
146 struct openpgp_packet_list *packets = NULL;
151 if (fingerprint->length > MAX_FINGERPRINT_LEN) {
155 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_FP)) {
156 size = fingerprint->length;
157 write(keyd_fd, &size, sizeof(size));
158 write(keyd_fd, fingerprint->fp, size);
160 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
161 if (keybuf.size > 0) {
162 keybuf.buffer = malloc(keybuf.size);
164 logthing(LOGTHING_TRACE,
165 "Getting %d bytes of key data.",
167 while (bytes >= 0 && count < keybuf.size) {
168 bytes = read(keyd_fd, &keybuf.buffer[count],
169 keybuf.size - count);
170 logthing(LOGTHING_TRACE,
171 "Read %d bytes.", bytes);
174 read_openpgp_stream(buffer_fetchchar, &keybuf,
176 parse_keys(packets, publickey);
177 free_packet_list(packets);
180 keybuf.buffer = NULL;
185 return (count > 0) ? 1 : 0;
189 * delete_key - Given a keyid delete the key from storage.
190 * @keyid: The keyid to delete.
191 * @intrans: If we're already in a transaction.
193 * This function deletes a public key from whatever storage mechanism we
194 * are using. Returns 0 if the key existed.
196 static int keyd_delete_key(struct onak_dbctx *dbctx,
197 uint64_t keyid, bool intrans)
199 int keyd_fd = (intptr_t) dbctx->priv;
201 if (keyd_send_cmd(keyd_fd, KEYD_CMD_DELETE)) {
202 write(keyd_fd, &keyid, sizeof(keyid));
209 * store_key - Takes a key and stores it.
210 * @publickey: A pointer to the public key to store.
211 * @intrans: If we're already in a transaction.
212 * @update: If true the key exists and should be updated.
214 * This function stores a public key in whatever storage mechanism we are
215 * using. intrans indicates if we're already in a transaction so don't
216 * need to start one. update indicates if the key already exists and is
217 * just being updated.
219 * TODO: Do we store multiple keys of the same id? Or only one and replace
222 static int keyd_store_key(struct onak_dbctx *dbctx,
223 struct openpgp_publickey *publickey, bool intrans,
226 int keyd_fd = (intptr_t) dbctx->priv;
227 struct buffer_ctx keybuf;
228 struct openpgp_packet_list *packets = NULL;
229 struct openpgp_packet_list *list_end = NULL;
230 struct openpgp_publickey *next = NULL;
232 enum keyd_ops cmd = KEYD_CMD_STORE;
234 if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
235 logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
240 cmd = KEYD_CMD_UPDATE;
243 if (keyd_send_cmd(keyd_fd, cmd)) {
246 keybuf.buffer = malloc(keybuf.size);
248 next = publickey->next;
249 publickey->next = NULL;
250 flatten_publickey(publickey,
253 publickey->next = next;
255 write_openpgp_stream(buffer_putchar, &keybuf, packets);
256 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
257 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
258 write(keyd_fd, keybuf.buffer, keybuf.offset);
260 free_packet_list(packets);
261 packets = list_end = NULL;
263 keybuf.buffer = NULL;
264 keybuf.size = keybuf.offset = 0;
271 * fetch_key_text - Trys to find the keys that contain the supplied text.
272 * @search: The text to search for.
273 * @publickey: A pointer to a structure to return the key in.
275 * This function searches for the supplied text and returns the keys that
278 static int keyd_fetch_key_text(struct onak_dbctx *dbctx,
280 struct openpgp_publickey **publickey)
282 int keyd_fd = (intptr_t) dbctx->priv;
283 struct buffer_ctx keybuf;
284 struct openpgp_packet_list *packets = NULL;
288 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_TEXT)) {
289 bytes = strlen(search);
290 write(keyd_fd, &bytes, sizeof(bytes));
291 write(keyd_fd, search, bytes);
293 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
294 if (keybuf.size > 0) {
295 keybuf.buffer = malloc(keybuf.size);
297 logthing(LOGTHING_TRACE,
298 "Getting %d bytes of key data.",
300 while (bytes >= 0 && count < keybuf.size) {
301 bytes = read(keyd_fd, &keybuf.buffer[count],
302 keybuf.size - count);
303 logthing(LOGTHING_TRACE,
304 "Read %d bytes.", bytes);
307 read_openpgp_stream(buffer_fetchchar, &keybuf,
309 parse_keys(packets, publickey);
310 free_packet_list(packets);
313 keybuf.buffer = NULL;
318 return (count > 0) ? 1 : 0;
323 static int keyd_fetch_key_skshash(struct onak_dbctx *dbctx,
324 const struct skshash *hash,
325 struct openpgp_publickey **publickey)
327 int keyd_fd = (intptr_t) dbctx->priv;
328 struct buffer_ctx keybuf;
329 struct openpgp_packet_list *packets = NULL;
333 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GET_SKSHASH)) {
334 write(keyd_fd, hash->hash, sizeof(hash->hash));
336 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
337 if (keybuf.size > 0) {
338 keybuf.buffer = malloc(keybuf.size);
340 logthing(LOGTHING_TRACE,
341 "Getting %d bytes of key data.",
343 while (bytes >= 0 && count < keybuf.size) {
344 bytes = read(keyd_fd, &keybuf.buffer[count],
345 keybuf.size - count);
346 logthing(LOGTHING_TRACE,
347 "Read %d bytes.", bytes);
350 read_openpgp_stream(buffer_fetchchar, &keybuf,
352 parse_keys(packets, publickey);
353 free_packet_list(packets);
356 keybuf.buffer = NULL;
361 return (count > 0) ? 1 : 0;
366 * getfullkeyid - Maps a 32bit key id to a 64bit one.
367 * @keyid: The 32bit keyid.
369 * This function maps a 32bit key id to the full 64bit one. It returns the
370 * full keyid. If the key isn't found a keyid of 0 is returned.
372 static uint64_t keyd_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
374 int keyd_fd = (intptr_t) dbctx->priv;
375 uint32_t cmd = KEYD_CMD_GETFULLKEYID;
377 if (keyd_send_cmd(keyd_fd, KEYD_CMD_GETFULLKEYID)) {
378 write(keyd_fd, &keyid, sizeof(keyid));
379 read(keyd_fd, &cmd, sizeof(cmd));
380 if (cmd != sizeof(keyid)) {
383 read(keyd_fd, &keyid, sizeof(keyid));
390 * iterate_keys - call a function once for each key in the db.
391 * @iterfunc: The function to call.
392 * @ctx: A context pointer
394 * Calls iterfunc once for each key in the database. ctx is passed
395 * unaltered to iterfunc. This function is intended to aid database dumps
396 * and statistic calculations.
398 * Returns the number of keys we iterated over.
400 static int keyd_iterate_keys(struct onak_dbctx *dbctx,
401 void (*iterfunc)(void *ctx,
402 struct openpgp_publickey *key), void *ctx)
404 int keyd_fd = (intptr_t) dbctx->priv;
405 struct buffer_ctx keybuf;
406 struct openpgp_packet_list *packets = NULL;
407 struct openpgp_publickey *key = NULL;
412 if (keyd_send_cmd(keyd_fd, KEYD_CMD_KEYITER)) {
414 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
415 while (keybuf.size > 0) {
416 keybuf.buffer = malloc(keybuf.size);
418 logthing(LOGTHING_TRACE,
419 "Getting %d bytes of key data.",
421 while (bytes >= 0 && count < keybuf.size) {
422 bytes = read(keyd_fd, &keybuf.buffer[count],
423 keybuf.size - count);
424 logthing(LOGTHING_TRACE,
425 "Read %d bytes.", bytes);
428 read_openpgp_stream(buffer_fetchchar, &keybuf,
430 parse_keys(packets, &key);
432 if (iterfunc != NULL && key != NULL) {
438 free_packet_list(packets);
441 keybuf.buffer = NULL;
442 keybuf.size = keybuf.offset = 0;
446 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
453 #define NEED_KEYID2UID 1
454 #define NEED_GETKEYSIGS 1
455 #define NEED_UPDATEKEYS 1
459 * cleanupdb - De-initialize the key database.
461 * This function should be called upon program exit to allow the DB to
462 * cleanup after itself.
464 static void keyd_cleanupdb(struct onak_dbctx *dbctx)
466 int keyd_fd = (intptr_t) dbctx->priv;
467 uint32_t cmd = KEYD_CMD_CLOSE;
469 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
470 logthing(LOGTHING_CRITICAL,
471 "Couldn't send close cmd: %s (%d)",
476 if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
477 logthing(LOGTHING_CRITICAL,
478 "Couldn't read close cmd reply: %s (%d)",
481 } else if (cmd != KEYD_REPLY_OK) {
482 logthing(LOGTHING_CRITICAL,
483 "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
486 if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
487 logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
490 if (close(keyd_fd) < 0) {
491 logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
501 * initdb - Initialize the key database.
502 * @readonly: If we'll only be reading the DB, not writing to it.
504 * This function should be called before any of the other functions in
505 * this file are called in order to allow the DB to be initialized ready
508 struct onak_dbctx *keydb_keyd_init(struct onak_db_config *dbcfg, bool readonly)
510 struct sockaddr_un sock;
511 uint32_t cmd = KEYD_CMD_UNKNOWN;
512 uint32_t reply = KEYD_REPLY_UNKNOWN_CMD;
515 struct onak_dbctx *dbctx;
517 dbctx = malloc(sizeof(*dbctx));
521 dbctx->config = dbcfg;
523 keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
525 logthing(LOGTHING_CRITICAL,
526 "Couldn't open socket: %s (%d)",
532 sock.sun_family = AF_UNIX;
533 snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
536 if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
537 logthing(LOGTHING_CRITICAL,
538 "Couldn't connect to socket %s: %s (%d)",
545 cmd = KEYD_CMD_VERSION;
546 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
547 logthing(LOGTHING_CRITICAL,
548 "Couldn't write version cmd: %s (%d)",
552 count = read(keyd_fd, &reply, sizeof(reply));
553 if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
554 count = read(keyd_fd, &reply, sizeof(reply));
555 if (count != sizeof(reply) || reply != sizeof(reply)) {
556 logthing(LOGTHING_CRITICAL,
557 "Error! Unexpected keyd version "
559 reply, sizeof(reply));
563 count = read(keyd_fd, &reply, sizeof(reply));
564 if (count != sizeof(reply)) {
565 logthing(LOGTHING_CRITICAL,
566 "Error! Unexpected keyd version "
568 count, sizeof(reply));
571 logthing(LOGTHING_DEBUG,
572 "keyd protocol version %d",
574 if (reply != keyd_version) {
575 logthing(LOGTHING_CRITICAL,
576 "Error! keyd protocol version "
577 "mismatch. (us = %d, it = %d)",
578 keyd_version, reply);
583 dbctx->priv = (void *) (intptr_t) keyd_fd;
584 dbctx->cleanupdb = keyd_cleanupdb;
585 dbctx->starttrans = keyd_starttrans;
586 dbctx->endtrans = keyd_endtrans;
587 dbctx->fetch_key_id = keyd_fetch_key_id;
588 dbctx->fetch_key_fp = keyd_fetch_key_fp;
589 dbctx->fetch_key_text = keyd_fetch_key_text;
590 dbctx->fetch_key_skshash = keyd_fetch_key_skshash;
591 dbctx->store_key = keyd_store_key;
592 dbctx->update_keys = generic_update_keys;
593 dbctx->delete_key = keyd_delete_key;
594 dbctx->getkeysigs = generic_getkeysigs;
595 dbctx->cached_getkeysigs = generic_cached_getkeysigs;
596 dbctx->keyid2uid = generic_keyid2uid;
597 dbctx->getfullkeyid = keyd_getfullkeyid;
598 dbctx->iterate_keys = keyd_iterate_keys;