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