2 * keydb_keyd.c - Routines to talk to keyd backend.
4 * Jonathan McDowell <noodles@earth.li>
6 * Copyright 2004 Project Purple
14 #include <sys/socket.h>
15 #include <sys/types.h>
19 #include "charfuncs.h"
23 #include "keystructs.h"
26 #include "onak-conf.h"
30 * keyd_fd - our file descriptor for the socket connection to keyd.
32 static int keyd_fd = -1;
35 * initdb - Initialize the key database.
36 * @readonly: If we'll only be reading the DB, not writing to it.
38 * This function should be called before any of the other functions in
39 * this file are called in order to allow the DB to be initialized ready
42 void initdb(bool readonly)
44 struct sockaddr_un sock;
45 int cmd = KEYD_CMD_UNKNOWN;
46 int reply = KEYD_REPLY_UNKNOWN_CMD;
49 keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
51 logthing(LOGTHING_CRITICAL,
52 "Couldn't open socket: %s (%d)",
58 sock.sun_family = AF_UNIX;
59 snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
62 if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
63 logthing(LOGTHING_CRITICAL,
64 "Couldn't connect to socket %s: %s (%d)",
71 cmd = KEYD_CMD_VERSION;
72 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
73 logthing(LOGTHING_CRITICAL,
74 "Couldn't write version cmd: %s (%d)",
78 count = read(keyd_fd, &reply, sizeof(reply));
79 if (count == sizeof(reply)) {
80 if (reply == KEYD_REPLY_OK) {
81 count = read(keyd_fd, &reply, sizeof(reply));
82 logthing(LOGTHING_DEBUG,
83 "keyd protocol version %d",
85 if (reply != keyd_version) {
86 logthing(LOGTHING_CRITICAL,
87 "Error! keyd protocol version "
88 "mismatch. (us = %d, it = %d)",
99 * cleanupdb - De-initialize the key database.
101 * This function should be called upon program exit to allow the DB to
102 * cleanup after itself.
106 if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
107 logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
117 * starttrans - Start a transaction.
119 * Start a transaction. Intended to be used if we're about to perform many
120 * operations on the database to help speed it all up, or if we want
121 * something to only succeed if all relevant operations are successful.
123 bool starttrans(void)
129 * endtrans - End a transaction.
131 * Ends a transaction.
139 * fetch_key - Given a keyid fetch the key from storage.
140 * @keyid: The keyid to fetch.
141 * @publickey: A pointer to a structure to return the key in.
142 * @intrans: If we're already in a transaction.
144 * This function returns a public key from whatever storage mechanism we
147 * TODO: What about keyid collisions? Should we use fingerprint instead?
149 int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
152 struct buffer_ctx keybuf;
153 struct openpgp_packet_list *packets = NULL;
154 int cmd = KEYD_CMD_GET;
158 write(keyd_fd, &cmd, sizeof(cmd));
159 read(keyd_fd, &cmd, sizeof(cmd));
160 if (cmd == KEYD_REPLY_OK) {
161 write(keyd_fd, &keyid, sizeof(keyid));
163 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
164 if (keybuf.size > 0) {
165 keybuf.buffer = malloc(keybuf.size);
167 logthing(LOGTHING_TRACE,
168 "Getting %d bytes of key data.",
170 while (bytes >= 0 && count < keybuf.size) {
171 bytes = read(keyd_fd, &keybuf.buffer[count],
172 keybuf.size - count);
173 logthing(LOGTHING_TRACE,
174 "Read %d bytes.", bytes);
177 read_openpgp_stream(buffer_fetchchar, &keybuf,
179 parse_keys(packets, publickey);
180 free_packet_list(packets);
183 keybuf.buffer = NULL;
188 return (count > 0) ? 1 : 0;
192 * store_key - Takes a key and stores it.
193 * @publickey: A pointer to the public key to store.
194 * @intrans: If we're already in a transaction.
195 * @update: If true the key exists and should be updated.
197 * This function stores a public key in whatever storage mechanism we are
198 * using. intrans indicates if we're already in a transaction so don't
199 * need to start one. update indicates if the key already exists and is
200 * just being updated.
202 * TODO: Do we store multiple keys of the same id? Or only one and replace
205 int store_key(struct openpgp_publickey *publickey, bool intrans, bool update)
207 struct buffer_ctx keybuf;
208 struct openpgp_packet_list *packets = NULL;
209 struct openpgp_packet_list *list_end = NULL;
210 struct openpgp_publickey *next = NULL;
211 int cmd = KEYD_CMD_STORE;
214 keyid = get_keyid(publickey);
217 delete_key(keyid, false);
220 write(keyd_fd, &cmd, sizeof(cmd));
221 read(keyd_fd, &cmd, sizeof(cmd));
222 if (cmd == KEYD_REPLY_OK) {
225 keybuf.buffer = malloc(keybuf.size);
227 next = publickey->next;
228 publickey->next = NULL;
229 flatten_publickey(publickey,
232 publickey->next = next;
234 write_openpgp_stream(buffer_putchar, &keybuf, packets);
235 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
236 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
237 write(keyd_fd, keybuf.buffer, keybuf.offset);
239 free_packet_list(packets);
240 packets = list_end = NULL;
242 keybuf.buffer = NULL;
243 keybuf.size = keybuf.offset = 0;
250 * delete_key - Given a keyid delete the key from storage.
251 * @keyid: The keyid to delete.
252 * @intrans: If we're already in a transaction.
254 * This function deletes a public key from whatever storage mechanism we
255 * are using. Returns 0 if the key existed.
257 int delete_key(uint64_t keyid, bool intrans)
259 int cmd = KEYD_CMD_DELETE;
261 write(keyd_fd, &cmd, sizeof(cmd));
262 read(keyd_fd, &cmd, sizeof(cmd));
263 if (cmd == KEYD_REPLY_OK) {
264 write(keyd_fd, &keyid, sizeof(keyid));
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 int fetch_key_text(const char *search, struct openpgp_publickey **publickey)
280 struct buffer_ctx keybuf;
281 struct openpgp_packet_list *packets = NULL;
282 int cmd = KEYD_CMD_GETTEXT;
286 write(keyd_fd, &cmd, sizeof(cmd));
287 read(keyd_fd, &cmd, sizeof(cmd));
288 if (cmd == KEYD_REPLY_OK) {
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;
324 * getfullkeyid - Maps a 32bit key id to a 64bit one.
325 * @keyid: The 32bit keyid.
327 * This function maps a 32bit key id to the full 64bit one. It returns the
328 * full keyid. If the key isn't found a keyid of 0 is returned.
330 uint64_t getfullkeyid(uint64_t keyid)
332 int cmd = KEYD_CMD_GETFULLKEYID;
334 write(keyd_fd, &cmd, sizeof(cmd));
335 read(keyd_fd, &cmd, sizeof(cmd));
336 if (cmd == KEYD_REPLY_OK) {
337 write(keyd_fd, &keyid, sizeof(keyid));
338 read(keyd_fd, &keyid, sizeof(keyid));
345 * dumpdb - dump the key database
346 * @filenamebase: The base filename to use for the dump.
348 * Dumps the database into one or more files, which contain pure OpenPGP
349 * that can be reimported into onak or gpg. filenamebase provides a base
350 * file name for the dump; several files may be created, all of which will
351 * begin with this string and then have a unique number and a .pgp
354 int dumpdb(char *filenamebase)
360 * iterate_keys - call a function once for each key in the db.
361 * @iterfunc: The function to call.
362 * @ctx: A context pointer
364 * Calls iterfunc once for each key in the database. ctx is passed
365 * unaltered to iterfunc. This function is intended to aid database dumps
366 * and statistic calculations.
368 * Returns the number of keys we iterated over.
370 int iterate_keys(void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
373 struct buffer_ctx keybuf;
374 struct openpgp_packet_list *packets = NULL;
375 struct openpgp_publickey *key = NULL;
376 int cmd = KEYD_CMD_KEYITER;
381 write(keyd_fd, &cmd, sizeof(cmd));
382 read(keyd_fd, &cmd, sizeof(cmd));
383 if (cmd == KEYD_REPLY_OK) {
385 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
386 while (keybuf.size > 0) {
387 keybuf.buffer = malloc(keybuf.size);
389 logthing(LOGTHING_TRACE,
390 "Getting %d bytes of key data.",
392 while (bytes >= 0 && count < keybuf.size) {
393 bytes = read(keyd_fd, &keybuf.buffer[count],
394 keybuf.size - count);
395 logthing(LOGTHING_TRACE,
396 "Read %d bytes.", bytes);
399 read_openpgp_stream(buffer_fetchchar, &keybuf,
401 parse_keys(packets, &key);
403 if (iterfunc != NULL && key != NULL) {
409 free_packet_list(packets);
412 keybuf.buffer = NULL;
413 keybuf.size = keybuf.offset = 0;
417 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
424 #define NEED_KEYID2UID 1
425 #define NEED_GETKEYSIGS 1
426 #define NEED_UPDATEKEYS 1