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