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