]> the.earth.li Git - onak.git/blob - keydb_keyd.c
Extend database backends to support fetching by key fingerprint
[onak.git] / keydb_keyd.c
1 /*
2  * keydb_keyd.c - Routines to talk to keyd backend.
3  *
4  * Copyright 2002-2004,2011 Jonathan McDowell <noodles@earth.li>
5  *
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.
9  *
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
13  * more details.
14  *
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.
18  */
19
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <sys/un.h>
28 #include <unistd.h>
29
30 #include "charfuncs.h"
31 #include "keyd.h"
32 #include "keydb.h"
33 #include "keyid.h"
34 #include "keystructs.h"
35 #include "log.h"
36 #include "mem.h"
37 #include "onak-conf.h"
38 #include "parsekey.h"
39
40 /**
41  *      keyd_fd - our file descriptor for the socket connection to keyd.
42  */
43 static int keyd_fd = -1;
44
45 /**
46  *      initdb - Initialize the key database.
47  *      @readonly: If we'll only be reading the DB, not writing to it.
48  *
49  *      This function should be called before any of the other functions in
50  *      this file are called in order to allow the DB to be initialized ready
51  *      for access.
52  */
53 static void keyd_initdb(bool readonly)
54 {
55         struct sockaddr_un sock;
56         uint32_t           cmd = KEYD_CMD_UNKNOWN;
57         uint32_t           reply = KEYD_REPLY_UNKNOWN_CMD;
58         ssize_t            count;
59
60         keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
61         if (keyd_fd < 0) {
62                 logthing(LOGTHING_CRITICAL,
63                                 "Couldn't open socket: %s (%d)",
64                                 strerror(errno),
65                                 errno);
66                 exit(EXIT_FAILURE);
67         }
68
69         sock.sun_family = AF_UNIX;
70         snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
71                         config.db_dir,
72                         KEYD_SOCKET);
73         if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
74                 logthing(LOGTHING_CRITICAL,
75                                 "Couldn't connect to socket %s: %s (%d)",
76                                 sock.sun_path,
77                                 strerror(errno),
78                                 errno);
79                 exit(EXIT_FAILURE);
80         }
81
82         cmd = KEYD_CMD_VERSION;
83         if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
84                 logthing(LOGTHING_CRITICAL,
85                                 "Couldn't write version cmd: %s (%d)",
86                                 strerror(errno),
87                                 errno);
88         } else {
89                 count = read(keyd_fd, &reply, sizeof(reply));
90                 if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
91                         count = read(keyd_fd, &reply, sizeof(reply));
92                         if (count != sizeof(reply) || reply != sizeof(reply)) {
93                                 logthing(LOGTHING_CRITICAL,
94                                         "Error! Unexpected keyd version "
95                                         "length: %d != %d",
96                                         reply, sizeof(reply));
97                                 exit(EXIT_FAILURE);
98                         }
99
100                         count = read(keyd_fd, &reply, sizeof(reply));
101                         logthing(LOGTHING_DEBUG,
102                                         "keyd protocol version %d",
103                                         reply);
104                         if (reply != keyd_version) {
105                                 logthing(LOGTHING_CRITICAL,
106                                         "Error! keyd protocol version "
107                                         "mismatch. (us = %d, it = %d)",
108                                                 keyd_version, reply);
109                         }
110                 }
111         }
112
113         return;
114 }
115
116 /**
117  *      cleanupdb - De-initialize the key database.
118  *
119  *      This function should be called upon program exit to allow the DB to
120  *      cleanup after itself.
121  */
122 static void keyd_cleanupdb(void)
123 {
124         uint32_t cmd = KEYD_CMD_CLOSE;
125
126         if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
127                 logthing(LOGTHING_CRITICAL,
128                                 "Couldn't send close cmd: %s (%d)",
129                                 strerror(errno),
130                                 errno);
131         }
132         
133         if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
134                 logthing(LOGTHING_CRITICAL,
135                         "Couldn't read close cmd reply: %s (%d)",
136                         strerror(errno),
137                         errno);
138         } else if (cmd != KEYD_REPLY_OK) {
139                 logthing(LOGTHING_CRITICAL,
140                         "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
141         }
142
143         if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
144                 logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
145                                 errno);
146         }
147         if (close(keyd_fd) < 0) {
148                 logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
149                                 errno);
150         }
151         keyd_fd = -1;
152
153         return;
154 }
155
156
157 /**
158  *      starttrans - Start a transaction.
159  *
160  *      Start a transaction. Intended to be used if we're about to perform many
161  *      operations on the database to help speed it all up, or if we want
162  *      something to only succeed if all relevant operations are successful.
163  */
164 static bool keyd_starttrans(void)
165 {
166         return true;
167 }
168
169 /**
170  *      endtrans - End a transaction.
171  *
172  *      Ends a transaction.
173  */
174 static void keyd_endtrans(void)
175 {
176         return;
177 }
178
179 /**
180  *      fetch_key - Given a keyid fetch the key from storage.
181  *      @keyid: The keyid to fetch.
182  *      @publickey: A pointer to a structure to return the key in.
183  *      @intrans: If we're already in a transaction.
184  *
185  *      This function returns a public key from whatever storage mechanism we
186  *      are using.
187  *
188  *      TODO: What about keyid collisions? Should we use fingerprint instead?
189  */
190 static int keyd_fetch_key_id(uint64_t keyid,
191                 struct openpgp_publickey **publickey,
192                 bool intrans)
193 {
194         struct buffer_ctx           keybuf;
195         struct openpgp_packet_list *packets = NULL;
196         uint32_t                    cmd = KEYD_CMD_GET_ID;
197         ssize_t                     bytes = 0;
198         ssize_t                     count = 0;
199
200         write(keyd_fd, &cmd, sizeof(cmd));
201         read(keyd_fd, &cmd, sizeof(cmd));
202         if (cmd == KEYD_REPLY_OK) {
203                 write(keyd_fd, &keyid, sizeof(keyid));
204                 keybuf.offset = 0;
205                 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
206                 if (keybuf.size > 0) {
207                         keybuf.buffer = malloc(keybuf.size);
208                         bytes = count = 0;
209                         logthing(LOGTHING_TRACE,
210                                         "Getting %d bytes of key data.",
211                                         keybuf.size);
212                         while (bytes >= 0 && count < keybuf.size) {
213                                 bytes = read(keyd_fd, &keybuf.buffer[count],
214                                                 keybuf.size - count);
215                                 logthing(LOGTHING_TRACE,
216                                                 "Read %d bytes.", bytes);
217                                 count += bytes;
218                         }
219                         read_openpgp_stream(buffer_fetchchar, &keybuf,
220                                         &packets, 0);
221                         parse_keys(packets, publickey);
222                         free_packet_list(packets);
223                         packets = NULL;
224                         free(keybuf.buffer);
225                         keybuf.buffer = NULL;
226                         keybuf.size = 0;
227                 }
228         }
229
230         return (count > 0) ? 1 : 0;
231 }
232
233 static int keyd_fetch_key_fp(uint8_t *fp, size_t fpsize,
234                 struct openpgp_publickey **publickey,
235                 bool intrans)
236 {
237         struct buffer_ctx           keybuf;
238         struct openpgp_packet_list *packets = NULL;
239         uint32_t                    cmd = KEYD_CMD_GET_FP;
240         ssize_t                     bytes = 0;
241         ssize_t                     count = 0;
242         uint8_t                     size;
243
244         if (fpsize > MAX_FINGERPRINT_LEN) {
245                 return 0;
246         }
247
248         write(keyd_fd, &cmd, sizeof(cmd));
249         read(keyd_fd, &cmd, sizeof(cmd));
250         if (cmd == KEYD_REPLY_OK) {
251                 size = fpsize;
252                 write(keyd_fd, &size, sizeof(size));
253                 write(keyd_fd, fp, size);
254                 keybuf.offset = 0;
255                 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
256                 if (keybuf.size > 0) {
257                         keybuf.buffer = malloc(keybuf.size);
258                         bytes = count = 0;
259                         logthing(LOGTHING_TRACE,
260                                         "Getting %d bytes of key data.",
261                                         keybuf.size);
262                         while (bytes >= 0 && count < keybuf.size) {
263                                 bytes = read(keyd_fd, &keybuf.buffer[count],
264                                                 keybuf.size - count);
265                                 logthing(LOGTHING_TRACE,
266                                                 "Read %d bytes.", bytes);
267                                 count += bytes;
268                         }
269                         read_openpgp_stream(buffer_fetchchar, &keybuf,
270                                         &packets, 0);
271                         parse_keys(packets, publickey);
272                         free_packet_list(packets);
273                         packets = NULL;
274                         free(keybuf.buffer);
275                         keybuf.buffer = NULL;
276                         keybuf.size = 0;
277                 }
278         }
279
280         return (count > 0) ? 1 : 0;
281 }
282
283 /**
284 *       delete_key - Given a keyid delete the key from storage.
285 *       @keyid: The keyid to delete.
286 *       @intrans: If we're already in a transaction.
287 *
288 *       This function deletes a public key from whatever storage mechanism we
289 *       are using. Returns 0 if the key existed.
290 */
291 static int keyd_delete_key(uint64_t keyid, bool intrans)
292 {
293         uint32_t cmd = KEYD_CMD_DELETE;
294
295         write(keyd_fd, &cmd, sizeof(cmd));
296         read(keyd_fd, &cmd, sizeof(cmd));
297         if (cmd == KEYD_REPLY_OK) {
298                 write(keyd_fd, &keyid, sizeof(keyid));
299         }
300
301         return 0;
302 }
303
304 /**
305  *      store_key - Takes a key and stores it.
306  *      @publickey: A pointer to the public key to store.
307  *      @intrans: If we're already in a transaction.
308  *      @update: If true the key exists and should be updated.
309  *
310  *      This function stores a public key in whatever storage mechanism we are
311  *      using. intrans indicates if we're already in a transaction so don't
312  *      need to start one. update indicates if the key already exists and is
313  *      just being updated.
314  *
315  *      TODO: Do we store multiple keys of the same id? Or only one and replace
316  *      it?
317  */
318 static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
319                 bool update)
320 {
321         struct buffer_ctx           keybuf;
322         struct openpgp_packet_list *packets = NULL;
323         struct openpgp_packet_list *list_end = NULL;
324         struct openpgp_publickey   *next = NULL;
325         uint32_t                    cmd = KEYD_CMD_STORE;
326         uint64_t                    keyid;
327
328         if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
329                 logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
330                 return 0;
331         }
332         
333         if (update) {
334                 keyd_delete_key(keyid, false);
335         }
336
337         write(keyd_fd, &cmd, sizeof(cmd));
338         read(keyd_fd, &cmd, sizeof(cmd));
339         if (cmd == KEYD_REPLY_OK) {
340                 keybuf.offset = 0;
341                 keybuf.size = 8192;
342                 keybuf.buffer = malloc(keybuf.size);
343
344                 next = publickey->next;
345                 publickey->next = NULL;
346                 flatten_publickey(publickey,
347                                 &packets,
348                                 &list_end);
349                 publickey->next = next;
350
351                 write_openpgp_stream(buffer_putchar, &keybuf, packets);
352                 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
353                 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
354                 write(keyd_fd, keybuf.buffer, keybuf.offset);
355
356                 free_packet_list(packets);
357                 packets = list_end = NULL;
358                 free(keybuf.buffer);
359                 keybuf.buffer = NULL;
360                 keybuf.size = keybuf.offset = 0;
361         }
362         
363         return 0;
364 }
365
366 /**
367  *      fetch_key_text - Trys to find the keys that contain the supplied text.
368  *      @search: The text to search for.
369  *      @publickey: A pointer to a structure to return the key in.
370  *
371  *      This function searches for the supplied text and returns the keys that
372  *      contain it.
373  */
374 static int keyd_fetch_key_text(const char *search,
375                 struct openpgp_publickey **publickey)
376 {
377         struct buffer_ctx           keybuf;
378         struct openpgp_packet_list *packets = NULL;
379         uint32_t                    cmd = KEYD_CMD_GET_TEXT;
380         ssize_t                     bytes = 0;
381         ssize_t                     count = 0;
382
383         write(keyd_fd, &cmd, sizeof(cmd));
384         read(keyd_fd, &cmd, sizeof(cmd));
385         if (cmd == KEYD_REPLY_OK) {
386                 bytes = strlen(search);
387                 write(keyd_fd, &bytes, sizeof(bytes));
388                 write(keyd_fd, search, bytes);
389                 keybuf.offset = 0;
390                 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
391                 if (keybuf.size > 0) {
392                         keybuf.buffer = malloc(keybuf.size);
393                         bytes = count = 0;
394                         logthing(LOGTHING_TRACE,
395                                         "Getting %d bytes of key data.",
396                                         keybuf.size);
397                         while (bytes >= 0 && count < keybuf.size) {
398                                 bytes = read(keyd_fd, &keybuf.buffer[count],
399                                                 keybuf.size - count);
400                                 logthing(LOGTHING_TRACE,
401                                                 "Read %d bytes.", bytes);
402                                 count += bytes;
403                         }
404                         read_openpgp_stream(buffer_fetchchar, &keybuf,
405                                         &packets, 0);
406                         parse_keys(packets, publickey);
407                         free_packet_list(packets);
408                         packets = NULL;
409                         free(keybuf.buffer);
410                         keybuf.buffer = NULL;
411                         keybuf.size = 0;
412                 }
413         }
414         
415         return (count > 0) ? 1 : 0;
416
417         return 0;
418 }
419
420 static int keyd_fetch_key_skshash(const struct skshash *hash,
421                 struct openpgp_publickey **publickey)
422 {
423         struct buffer_ctx           keybuf;
424         struct openpgp_packet_list *packets = NULL;
425         uint32_t                    cmd = KEYD_CMD_GET_SKSHASH;
426         ssize_t                     bytes = 0;
427         ssize_t                     count = 0;
428
429         write(keyd_fd, &cmd, sizeof(cmd));
430         read(keyd_fd, &cmd, sizeof(cmd));
431         if (cmd == KEYD_REPLY_OK) {
432                 write(keyd_fd, hash->hash, sizeof(hash->hash));
433                 keybuf.offset = 0;
434                 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
435                 if (keybuf.size > 0) {
436                         keybuf.buffer = malloc(keybuf.size);
437                         bytes = count = 0;
438                         logthing(LOGTHING_TRACE,
439                                         "Getting %d bytes of key data.",
440                                         keybuf.size);
441                         while (bytes >= 0 && count < keybuf.size) {
442                                 bytes = read(keyd_fd, &keybuf.buffer[count],
443                                                 keybuf.size - count);
444                                 logthing(LOGTHING_TRACE,
445                                                 "Read %d bytes.", bytes);
446                                 count += bytes;
447                         }
448                         read_openpgp_stream(buffer_fetchchar, &keybuf,
449                                         &packets, 0);
450                         parse_keys(packets, publickey);
451                         free_packet_list(packets);
452                         packets = NULL;
453                         free(keybuf.buffer);
454                         keybuf.buffer = NULL;
455                         keybuf.size = 0;
456                 }
457         }
458         
459         return (count > 0) ? 1 : 0;
460 }
461
462
463 /**
464  *      getfullkeyid - Maps a 32bit key id to a 64bit one.
465  *      @keyid: The 32bit keyid.
466  *
467  *      This function maps a 32bit key id to the full 64bit one. It returns the
468  *      full keyid. If the key isn't found a keyid of 0 is returned.
469  */
470 static uint64_t keyd_getfullkeyid(uint64_t keyid)
471 {
472         uint32_t cmd = KEYD_CMD_GETFULLKEYID;
473
474         write(keyd_fd, &cmd, sizeof(cmd));
475         read(keyd_fd, &cmd, sizeof(cmd));
476         if (cmd == KEYD_REPLY_OK) {
477                 write(keyd_fd, &keyid, sizeof(keyid));
478                 read(keyd_fd, &cmd, sizeof(cmd));
479                 if (cmd != sizeof(keyid)) {
480                         return 0;
481                 }
482                 read(keyd_fd, &keyid, sizeof(keyid));
483         }
484
485         return keyid;
486 }
487
488 /**
489  *      iterate_keys - call a function once for each key in the db.
490  *      @iterfunc: The function to call.
491  *      @ctx: A context pointer
492  *
493  *      Calls iterfunc once for each key in the database. ctx is passed
494  *      unaltered to iterfunc. This function is intended to aid database dumps
495  *      and statistic calculations.
496  *
497  *      Returns the number of keys we iterated over.
498  */
499 static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
500                 struct openpgp_publickey *key), void *ctx)
501 {
502         struct buffer_ctx           keybuf;
503         struct openpgp_packet_list *packets = NULL;
504         struct openpgp_publickey   *key = NULL;
505         uint32_t                    cmd = KEYD_CMD_KEYITER;
506         ssize_t                     bytes = 0;
507         ssize_t                     count = 0;
508         int                         numkeys = 0;
509
510         write(keyd_fd, &cmd, sizeof(cmd));
511         read(keyd_fd, &cmd, sizeof(cmd));
512         if (cmd == KEYD_REPLY_OK) {
513                 keybuf.offset = 0;
514                 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
515                 while (keybuf.size > 0) {
516                         keybuf.buffer = malloc(keybuf.size);
517                         bytes = count = 0;
518                         logthing(LOGTHING_TRACE,
519                                         "Getting %d bytes of key data.",
520                                         keybuf.size);
521                         while (bytes >= 0 && count < keybuf.size) {
522                                 bytes = read(keyd_fd, &keybuf.buffer[count],
523                                                 keybuf.size - count);
524                                 logthing(LOGTHING_TRACE,
525                                                 "Read %d bytes.", bytes);
526                                 count += bytes;
527                         }
528                         read_openpgp_stream(buffer_fetchchar, &keybuf,
529                                         &packets, 0);
530                         parse_keys(packets, &key);
531
532                         if (iterfunc != NULL && key != NULL) {
533                                 iterfunc(ctx, key);
534                         }
535
536                         free_publickey(key);
537                         key = NULL;
538                         free_packet_list(packets);
539                         packets = NULL;
540                         free(keybuf.buffer);
541                         keybuf.buffer = NULL;
542                         keybuf.size = keybuf.offset = 0;
543
544                         numkeys++;
545
546                         read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
547                 }
548         }
549         
550         return numkeys;
551 }
552
553 #define NEED_KEYID2UID 1
554 #define NEED_GETKEYSIGS 1
555 #define NEED_UPDATEKEYS 1
556 #include "keydb.c"
557
558 struct dbfuncs keydb_keyd_funcs = {
559         .initdb                 = keyd_initdb,
560         .cleanupdb              = keyd_cleanupdb,
561         .starttrans             = keyd_starttrans,
562         .endtrans               = keyd_endtrans,
563         .fetch_key_id           = keyd_fetch_key_id,
564         .fetch_key_fp           = keyd_fetch_key_fp,
565         .fetch_key_text         = keyd_fetch_key_text,
566         .fetch_key_skshash      = keyd_fetch_key_skshash,
567         .store_key              = keyd_store_key,
568         .update_keys            = generic_update_keys,
569         .delete_key             = keyd_delete_key,
570         .getkeysigs             = generic_getkeysigs,
571         .cached_getkeysigs      = generic_cached_getkeysigs,
572         .keyid2uid              = generic_keyid2uid,
573         .getfullkeyid           = keyd_getfullkeyid,
574         .iterate_keys           = keyd_iterate_keys,
575 };