]> the.earth.li Git - onak.git/blob - keydb_keyd.c
Use full key id in key id retrieval test + add separate short key id test
[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 /**
63  *      fetch_key - Given a keyid fetch the key from storage.
64  *      @keyid: The keyid to fetch.
65  *      @publickey: A pointer to a structure to return the key in.
66  *      @intrans: If we're already in a transaction.
67  *
68  *      This function returns a public key from whatever storage mechanism we
69  *      are using.
70  *
71  *      TODO: What about keyid collisions? Should we use fingerprint instead?
72  */
73 static int keyd_fetch_key_id(struct onak_dbctx *dbctx,
74                 uint64_t keyid,
75                 struct openpgp_publickey **publickey,
76                 bool intrans)
77 {
78         int keyd_fd = (intptr_t) dbctx->priv;
79         struct buffer_ctx           keybuf;
80         struct openpgp_packet_list *packets = NULL;
81         uint32_t                    cmd = KEYD_CMD_GET_ID;
82         ssize_t                     bytes = 0;
83         ssize_t                     count = 0;
84
85         write(keyd_fd, &cmd, sizeof(cmd));
86         read(keyd_fd, &cmd, sizeof(cmd));
87         if (cmd == KEYD_REPLY_OK) {
88                 write(keyd_fd, &keyid, sizeof(keyid));
89                 keybuf.offset = 0;
90                 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
91                 if (keybuf.size > 0) {
92                         keybuf.buffer = malloc(keybuf.size);
93                         bytes = count = 0;
94                         logthing(LOGTHING_TRACE,
95                                         "Getting %d bytes of key data.",
96                                         keybuf.size);
97                         while (bytes >= 0 && count < keybuf.size) {
98                                 bytes = read(keyd_fd, &keybuf.buffer[count],
99                                                 keybuf.size - count);
100                                 logthing(LOGTHING_TRACE,
101                                                 "Read %d bytes.", bytes);
102                                 count += bytes;
103                         }
104                         read_openpgp_stream(buffer_fetchchar, &keybuf,
105                                         &packets, 0);
106                         parse_keys(packets, publickey);
107                         free_packet_list(packets);
108                         packets = NULL;
109                         free(keybuf.buffer);
110                         keybuf.buffer = NULL;
111                         keybuf.size = 0;
112                 }
113         }
114
115         return (count > 0) ? 1 : 0;
116 }
117
118 static int keyd_fetch_key_fp(struct onak_dbctx *dbctx,
119                 uint8_t *fp, size_t fpsize,
120                 struct openpgp_publickey **publickey,
121                 bool intrans)
122 {
123         int keyd_fd = (intptr_t) dbctx->priv;
124         struct buffer_ctx           keybuf;
125         struct openpgp_packet_list *packets = NULL;
126         uint32_t                    cmd = KEYD_CMD_GET_FP;
127         ssize_t                     bytes = 0;
128         ssize_t                     count = 0;
129         uint8_t                     size;
130
131         if (fpsize > MAX_FINGERPRINT_LEN) {
132                 return 0;
133         }
134
135         write(keyd_fd, &cmd, sizeof(cmd));
136         read(keyd_fd, &cmd, sizeof(cmd));
137         if (cmd == KEYD_REPLY_OK) {
138                 size = fpsize;
139                 write(keyd_fd, &size, sizeof(size));
140                 write(keyd_fd, fp, size);
141                 keybuf.offset = 0;
142                 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
143                 if (keybuf.size > 0) {
144                         keybuf.buffer = malloc(keybuf.size);
145                         bytes = count = 0;
146                         logthing(LOGTHING_TRACE,
147                                         "Getting %d bytes of key data.",
148                                         keybuf.size);
149                         while (bytes >= 0 && count < keybuf.size) {
150                                 bytes = read(keyd_fd, &keybuf.buffer[count],
151                                                 keybuf.size - count);
152                                 logthing(LOGTHING_TRACE,
153                                                 "Read %d bytes.", bytes);
154                                 count += bytes;
155                         }
156                         read_openpgp_stream(buffer_fetchchar, &keybuf,
157                                         &packets, 0);
158                         parse_keys(packets, publickey);
159                         free_packet_list(packets);
160                         packets = NULL;
161                         free(keybuf.buffer);
162                         keybuf.buffer = NULL;
163                         keybuf.size = 0;
164                 }
165         }
166
167         return (count > 0) ? 1 : 0;
168 }
169
170 /**
171 *       delete_key - Given a keyid delete the key from storage.
172 *       @keyid: The keyid to delete.
173 *       @intrans: If we're already in a transaction.
174 *
175 *       This function deletes a public key from whatever storage mechanism we
176 *       are using. Returns 0 if the key existed.
177 */
178 static int keyd_delete_key(struct onak_dbctx *dbctx,
179                 uint64_t keyid, bool intrans)
180 {
181         int keyd_fd = (intptr_t) dbctx->priv;
182         uint32_t cmd = KEYD_CMD_DELETE;
183
184         write(keyd_fd, &cmd, sizeof(cmd));
185         read(keyd_fd, &cmd, sizeof(cmd));
186         if (cmd == KEYD_REPLY_OK) {
187                 write(keyd_fd, &keyid, sizeof(keyid));
188         }
189
190         return 0;
191 }
192
193 /**
194  *      store_key - Takes a key and stores it.
195  *      @publickey: A pointer to the public key to store.
196  *      @intrans: If we're already in a transaction.
197  *      @update: If true the key exists and should be updated.
198  *
199  *      This function stores a public key in whatever storage mechanism we are
200  *      using. intrans indicates if we're already in a transaction so don't
201  *      need to start one. update indicates if the key already exists and is
202  *      just being updated.
203  *
204  *      TODO: Do we store multiple keys of the same id? Or only one and replace
205  *      it?
206  */
207 static int keyd_store_key(struct onak_dbctx *dbctx,
208                 struct openpgp_publickey *publickey, bool intrans,
209                 bool update)
210 {
211         int keyd_fd = (intptr_t) dbctx->priv;
212         struct buffer_ctx           keybuf;
213         struct openpgp_packet_list *packets = NULL;
214         struct openpgp_packet_list *list_end = NULL;
215         struct openpgp_publickey   *next = NULL;
216         uint32_t                    cmd = KEYD_CMD_STORE;
217         uint64_t                    keyid;
218
219         if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
220                 logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
221                 return 0;
222         }
223
224         if (update) {
225                 keyd_delete_key(dbctx, keyid, false);
226         }
227
228         write(keyd_fd, &cmd, sizeof(cmd));
229         read(keyd_fd, &cmd, sizeof(cmd));
230         if (cmd == KEYD_REPLY_OK) {
231                 keybuf.offset = 0;
232                 keybuf.size = 8192;
233                 keybuf.buffer = malloc(keybuf.size);
234
235                 next = publickey->next;
236                 publickey->next = NULL;
237                 flatten_publickey(publickey,
238                                 &packets,
239                                 &list_end);
240                 publickey->next = next;
241
242                 write_openpgp_stream(buffer_putchar, &keybuf, packets);
243                 logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
244                 write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
245                 write(keyd_fd, keybuf.buffer, keybuf.offset);
246
247                 free_packet_list(packets);
248                 packets = list_end = NULL;
249                 free(keybuf.buffer);
250                 keybuf.buffer = NULL;
251                 keybuf.size = keybuf.offset = 0;
252         }
253
254         return 0;
255 }
256
257 /**
258  *      fetch_key_text - Trys to find the keys that contain the supplied text.
259  *      @search: The text to search for.
260  *      @publickey: A pointer to a structure to return the key in.
261  *
262  *      This function searches for the supplied text and returns the keys that
263  *      contain it.
264  */
265 static int keyd_fetch_key_text(struct onak_dbctx *dbctx,
266                 const char *search,
267                 struct openpgp_publickey **publickey)
268 {
269         int keyd_fd = (intptr_t) dbctx->priv;
270         struct buffer_ctx           keybuf;
271         struct openpgp_packet_list *packets = NULL;
272         uint32_t                    cmd = KEYD_CMD_GET_TEXT;
273         ssize_t                     bytes = 0;
274         ssize_t                     count = 0;
275
276         write(keyd_fd, &cmd, sizeof(cmd));
277         read(keyd_fd, &cmd, sizeof(cmd));
278         if (cmd == KEYD_REPLY_OK) {
279                 bytes = strlen(search);
280                 write(keyd_fd, &bytes, sizeof(bytes));
281                 write(keyd_fd, search, bytes);
282                 keybuf.offset = 0;
283                 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
284                 if (keybuf.size > 0) {
285                         keybuf.buffer = malloc(keybuf.size);
286                         bytes = count = 0;
287                         logthing(LOGTHING_TRACE,
288                                         "Getting %d bytes of key data.",
289                                         keybuf.size);
290                         while (bytes >= 0 && count < keybuf.size) {
291                                 bytes = read(keyd_fd, &keybuf.buffer[count],
292                                                 keybuf.size - count);
293                                 logthing(LOGTHING_TRACE,
294                                                 "Read %d bytes.", bytes);
295                                 count += bytes;
296                         }
297                         read_openpgp_stream(buffer_fetchchar, &keybuf,
298                                         &packets, 0);
299                         parse_keys(packets, publickey);
300                         free_packet_list(packets);
301                         packets = NULL;
302                         free(keybuf.buffer);
303                         keybuf.buffer = NULL;
304                         keybuf.size = 0;
305                 }
306         }
307
308         return (count > 0) ? 1 : 0;
309
310         return 0;
311 }
312
313 static int keyd_fetch_key_skshash(struct onak_dbctx *dbctx,
314                 const struct skshash *hash,
315                 struct openpgp_publickey **publickey)
316 {
317         int keyd_fd = (intptr_t) dbctx->priv;
318         struct buffer_ctx           keybuf;
319         struct openpgp_packet_list *packets = NULL;
320         uint32_t                    cmd = KEYD_CMD_GET_SKSHASH;
321         ssize_t                     bytes = 0;
322         ssize_t                     count = 0;
323
324         write(keyd_fd, &cmd, sizeof(cmd));
325         read(keyd_fd, &cmd, sizeof(cmd));
326         if (cmd == KEYD_REPLY_OK) {
327                 write(keyd_fd, hash->hash, sizeof(hash->hash));
328                 keybuf.offset = 0;
329                 read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
330                 if (keybuf.size > 0) {
331                         keybuf.buffer = malloc(keybuf.size);
332                         bytes = count = 0;
333                         logthing(LOGTHING_TRACE,
334                                         "Getting %d bytes of key data.",
335                                         keybuf.size);
336                         while (bytes >= 0 && count < keybuf.size) {
337                                 bytes = read(keyd_fd, &keybuf.buffer[count],
338                                                 keybuf.size - count);
339                                 logthing(LOGTHING_TRACE,
340                                                 "Read %d bytes.", bytes);
341                                 count += bytes;
342                         }
343                         read_openpgp_stream(buffer_fetchchar, &keybuf,
344                                         &packets, 0);
345                         parse_keys(packets, publickey);
346                         free_packet_list(packets);
347                         packets = NULL;
348                         free(keybuf.buffer);
349                         keybuf.buffer = NULL;
350                         keybuf.size = 0;
351                 }
352         }
353
354         return (count > 0) ? 1 : 0;
355 }
356
357
358 /**
359  *      getfullkeyid - Maps a 32bit key id to a 64bit one.
360  *      @keyid: The 32bit keyid.
361  *
362  *      This function maps a 32bit key id to the full 64bit one. It returns the
363  *      full keyid. If the key isn't found a keyid of 0 is returned.
364  */
365 static uint64_t keyd_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
366 {
367         int keyd_fd = (intptr_t) dbctx->priv;
368         uint32_t cmd = KEYD_CMD_GETFULLKEYID;
369
370         write(keyd_fd, &cmd, sizeof(cmd));
371         read(keyd_fd, &cmd, sizeof(cmd));
372         if (cmd == KEYD_REPLY_OK) {
373                 write(keyd_fd, &keyid, sizeof(keyid));
374                 read(keyd_fd, &cmd, sizeof(cmd));
375                 if (cmd != sizeof(keyid)) {
376                         return 0;
377                 }
378                 read(keyd_fd, &keyid, sizeof(keyid));
379         }
380
381         return keyid;
382 }
383
384 /**
385  *      iterate_keys - call a function once for each key in the db.
386  *      @iterfunc: The function to call.
387  *      @ctx: A context pointer
388  *
389  *      Calls iterfunc once for each key in the database. ctx is passed
390  *      unaltered to iterfunc. This function is intended to aid database dumps
391  *      and statistic calculations.
392  *
393  *      Returns the number of keys we iterated over.
394  */
395 static int keyd_iterate_keys(struct onak_dbctx *dbctx,
396                 void (*iterfunc)(void *ctx,
397                 struct openpgp_publickey *key), void *ctx)
398 {
399         int keyd_fd = (intptr_t) dbctx->priv;
400         struct buffer_ctx           keybuf;
401         struct openpgp_packet_list *packets = NULL;
402         struct openpgp_publickey   *key = NULL;
403         uint32_t                    cmd = KEYD_CMD_KEYITER;
404         ssize_t                     bytes = 0;
405         ssize_t                     count = 0;
406         int                         numkeys = 0;
407
408         write(keyd_fd, &cmd, sizeof(cmd));
409         read(keyd_fd, &cmd, sizeof(cmd));
410         if (cmd == KEYD_REPLY_OK) {
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(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
520         keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
521         if (keyd_fd < 0) {
522                 logthing(LOGTHING_CRITICAL,
523                                 "Couldn't open socket: %s (%d)",
524                                 strerror(errno),
525                                 errno);
526                 exit(EXIT_FAILURE);
527         }
528
529         sock.sun_family = AF_UNIX;
530         snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
531                         config.db_dir,
532                         KEYD_SOCKET);
533         if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
534                 logthing(LOGTHING_CRITICAL,
535                                 "Couldn't connect to socket %s: %s (%d)",
536                                 sock.sun_path,
537                                 strerror(errno),
538                                 errno);
539                 exit(EXIT_FAILURE);
540         }
541
542         cmd = KEYD_CMD_VERSION;
543         if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
544                 logthing(LOGTHING_CRITICAL,
545                                 "Couldn't write version cmd: %s (%d)",
546                                 strerror(errno),
547                                 errno);
548         } else {
549                 count = read(keyd_fd, &reply, sizeof(reply));
550                 if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
551                         count = read(keyd_fd, &reply, sizeof(reply));
552                         if (count != sizeof(reply) || reply != sizeof(reply)) {
553                                 logthing(LOGTHING_CRITICAL,
554                                         "Error! Unexpected keyd version "
555                                         "length: %d != %d",
556                                         reply, sizeof(reply));
557                                 exit(EXIT_FAILURE);
558                         }
559
560                         count = read(keyd_fd, &reply, sizeof(reply));
561                         if (count != sizeof(reply)) {
562                                 logthing(LOGTHING_CRITICAL,
563                                         "Error! Unexpected keyd version "
564                                         "length: %d != %d",
565                                         count, sizeof(reply));
566                                 exit(EXIT_FAILURE);
567                         }
568                         logthing(LOGTHING_DEBUG,
569                                         "keyd protocol version %d",
570                                         reply);
571                         if (reply != keyd_version) {
572                                 logthing(LOGTHING_CRITICAL,
573                                         "Error! keyd protocol version "
574                                         "mismatch. (us = %d, it = %d)",
575                                                 keyd_version, reply);
576                         }
577                 }
578         }
579
580         dbctx->priv                     = (void *) (intptr_t) keyd_fd;
581         dbctx->cleanupdb                = keyd_cleanupdb;
582         dbctx->starttrans               = keyd_starttrans;
583         dbctx->endtrans                 = keyd_endtrans;
584         dbctx->fetch_key_id             = keyd_fetch_key_id;
585         dbctx->fetch_key_fp             = keyd_fetch_key_fp;
586         dbctx->fetch_key_text           = keyd_fetch_key_text;
587         dbctx->fetch_key_skshash        = keyd_fetch_key_skshash;
588         dbctx->store_key                = keyd_store_key;
589         dbctx->update_keys              = generic_update_keys;
590         dbctx->delete_key               = keyd_delete_key;
591         dbctx->getkeysigs               = generic_getkeysigs;
592         dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
593         dbctx->keyid2uid                = generic_keyid2uid;
594         dbctx->getfullkeyid             = keyd_getfullkeyid;
595         dbctx->iterate_keys             = keyd_iterate_keys;
596
597         return dbctx;
598 }