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