]> the.earth.li Git - onak.git/blob - keydb.c
Update GPL location to URL rather than postal address
[onak.git] / keydb.c
1 /*
2  * keydb.c - Routines for DB access that just use store/fetch.
3  *
4  * Copyright 2002-2004 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 /**
20  *      The routines in this file are meant to be used as an initial step when
21  *      adding a new db access module. They provide various functions required
22  *      of the db access module using only the store and fetch functions. As
23  *      they need to parse the actual OpenPGP data to work they are a lot
24  *      slower than custom functions however.
25  */
26
27 #include <stdbool.h>
28 #include <stdio.h>
29
30 #include "decodekey.h"
31 #include "hash.h"
32 #include "keydb.h"
33 #include "keyid.h"
34 #include "keystructs.h"
35 #include "ll.h"
36 #include "mem.h"
37 #include "merge.h"
38 #include "openpgp.h"
39 #include "sendsync.h"
40 #include "stats.h"
41
42 #ifdef NEED_KEYID2UID
43 /**
44  *      keyid2uid - Takes a keyid and returns the primary UID for it.
45  *      @keyid: The keyid to lookup.
46  */
47 char *generic_keyid2uid(struct onak_dbctx *dbctx, uint64_t keyid)
48 {
49         struct openpgp_publickey *publickey = NULL;
50         struct openpgp_signedpacket_list *curuid = NULL;
51         char buf[1024];
52
53         buf[0]=0;
54         if (dbctx->fetch_key_id(dbctx, keyid, &publickey, false) &&
55                         publickey != NULL) {
56                 curuid = publickey->uids;
57                 while (curuid != NULL && buf[0] == 0) {
58                         if (curuid->packet->tag == OPENPGP_PACKET_UID) {
59                                 snprintf(buf, 1023, "%.*s",
60                                                 (int) curuid->packet->length,
61                                                 curuid->packet->data);
62                         }
63                         curuid = curuid -> next;
64                 }
65                 free_publickey(publickey);
66         }
67
68         if (buf[0] == 0) {
69                 return NULL;
70         } else {
71                 return strdup(buf);
72         }
73 }
74 #endif
75
76 #ifdef NEED_GETKEYSIGS
77 /**
78  *      getkeysigs - Gets a linked list of the signatures on a key.
79  *      @keyid: The keyid to get the sigs for.
80  *      @revoked: Is the key revoked?
81  *
82  *      This function gets the list of signatures on a key. Used for key 
83  *      indexing and doing stats bits. If revoked is non-NULL then if the key
84  *      is revoked it's set to true.
85  */
86 struct ll *generic_getkeysigs(struct onak_dbctx *dbctx,
87                 uint64_t keyid, bool *revoked)
88 {
89         struct ll *sigs = NULL;
90         struct openpgp_signedpacket_list *uids = NULL;
91         struct openpgp_publickey *publickey = NULL;
92
93         dbctx->fetch_key_id(dbctx, keyid, &publickey, false);
94         
95         if (publickey != NULL) {
96                 for (uids = publickey->uids; uids != NULL; uids = uids->next) {
97                         sigs = keysigs(sigs, uids->sigs);
98                 }
99                 if (revoked != NULL) {
100                         *revoked = publickey->revoked;
101                 }
102                 free_publickey(publickey);
103         }
104
105         return sigs;
106 }
107 #endif
108
109 /**
110  *      cached_getkeysigs - Gets the signatures on a key.
111  *      @keyid: The key we want the signatures for.
112  *      
113  *      This function gets the signatures on a key. It's the same as the
114  *      getkeysigs function above except we use the hash module to cache the
115  *      data so if we need it again it's already loaded.
116  */
117 struct ll *generic_cached_getkeysigs(struct onak_dbctx *dbctx, uint64_t keyid)
118 {
119         struct stats_key *key = NULL;
120         struct stats_key *signedkey = NULL;
121         struct ll        *cursig = NULL;
122         struct ll        *sigs = NULL;
123         bool              revoked = false;
124
125         if (keyid == 0)  {
126                 return NULL;
127         }
128
129         key = findinhash(keyid);
130
131         if (key == NULL || key->gotsigs == false) {
132                 sigs = dbctx->getkeysigs(dbctx, keyid, &revoked);
133                 if (sigs == NULL) {
134                         return NULL;
135                 }
136                 if (key == NULL) {
137                         key = createandaddtohash(keyid);
138                 }
139                 key->sigs = sigs;
140                 key->revoked = revoked;
141                 for (cursig = key->sigs; cursig != NULL;
142                                 cursig = cursig->next) {
143                         signedkey = (struct stats_key *) cursig->object;
144                         signedkey->signs = lladd(signedkey->signs, key);
145                 }
146                 key->gotsigs = true;
147         }
148
149         return key->sigs;
150 }
151
152 #ifdef NEED_GETFULLKEYID
153 /**
154  *      getfullkeyid - Maps a 32bit key id to a 64bit one.
155  *      @keyid: The 32bit keyid.
156  *
157  *      This function maps a 32bit key id to the full 64bit one. It returns the
158  *      full keyid. If the key isn't found a keyid of 0 is returned.
159  */
160 uint64_t generic_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
161 {
162         struct openpgp_publickey *publickey = NULL;
163
164         if (keyid < 0x100000000LL) {
165                 dbctx->fetch_key_id(dbctx, keyid, &publickey, false);
166                 if (publickey != NULL) {
167                         get_keyid(publickey, &keyid);
168                         free_publickey(publickey);
169                         publickey = NULL;
170                 } else {
171                         keyid = 0;
172                 }
173         }
174         
175         return keyid;
176 }
177 #endif
178
179 #ifdef NEED_UPDATEKEYS
180 /**
181  *      update_keys - Takes a list of public keys and updates them in the DB.
182  *      @keys: The keys to update in the DB.
183  *      @sendsync: Should we send a sync mail to our peers.
184  *
185  *      Takes a list of keys and adds them to the database, merging them with
186  *      the key in the database if it's already present there. The key list is
187  *      update to contain the minimum set of updates required to get from what
188  *      we had before to what we have now (ie the set of data that was added to
189  *      the DB). Returns the number of entirely new keys added.
190  */
191 int generic_update_keys(struct onak_dbctx *dbctx,
192                 struct openpgp_publickey **keys, bool sendsync)
193 {
194         struct openpgp_publickey *curkey = NULL;
195         struct openpgp_publickey *oldkey = NULL;
196         struct openpgp_publickey *prev = NULL;
197         int newkeys = 0;
198         bool intrans;
199         uint64_t keyid;
200
201         for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
202                 intrans = dbctx->starttrans(dbctx);
203                 get_keyid(curkey, &keyid);
204                 logthing(LOGTHING_INFO,
205                         "Fetching key 0x%" PRIX64 ", result: %d",
206                         keyid,
207                         dbctx->fetch_key_id(dbctx, keyid, &oldkey,
208                                         intrans));
209
210                 /*
211                  * If we already have the key stored in the DB then merge it
212                  * with the new one that's been supplied. Otherwise the key
213                  * we've just got is the one that goes in the DB and also the
214                  * one that we send out.
215                  */
216                 if (oldkey != NULL) {
217                         merge_keys(oldkey, curkey);
218                         if (curkey->sigs == NULL &&
219                                         curkey->uids == NULL &&
220                                         curkey->subkeys == NULL) {
221                                 if (prev == NULL) {
222                                         *keys = curkey->next;
223                                 } else {
224                                         prev->next = curkey->next;
225                                         curkey->next = NULL;
226                                         free_publickey(curkey);
227                                         curkey = prev;
228                                 }
229                         } else {
230                                 prev = curkey;
231                                 logthing(LOGTHING_INFO,
232                                         "Merged key; storing updated key.");
233                                 dbctx->store_key(dbctx, oldkey, intrans,
234                                         true);
235                         }
236                         free_publickey(oldkey);
237                         oldkey = NULL;
238                 } else {
239                         logthing(LOGTHING_INFO,
240                                 "Storing completely new key.");
241                         dbctx->store_key(dbctx, curkey, intrans, false);
242                         newkeys++;
243                 }
244                 dbctx->endtrans(dbctx);
245         }
246
247         if (sendsync && keys != NULL) {
248                 sendkeysync(*keys);
249         }
250
251         return newkeys;
252 }
253 #endif /* NEED_UPDATEKEYS */
254
255 #ifdef NEED_GET_FP
256 static int generic_fetch_key_fp(struct onak_dbctx *dbctx,
257                 struct openpgp_fingerprint *fingerprint,
258                 struct openpgp_publickey **publickey, bool intrans)
259 {
260         uint64_t keyid;
261         int i;
262
263         if (fingerprint->length > MAX_FINGERPRINT_LEN) {
264                 return 0;
265         }
266
267         /*
268          * We assume if the backend is using this function it's not storing
269          * anything bigger than the 64 bit key ID and just truncate the
270          * fingerprint to get that value. This doesn't work for v3 keys,
271          * but there's no way to map from v3 fingerprint to v3 key ID so
272          * if the backend can't do it we're going to fail anyway.
273          */
274         keyid = 0;
275         for (i = (fingerprint->length - 8); i < fingerprint->length; i++) {
276                 keyid = (keyid << 8) + fingerprint->fp[i];
277         }
278
279         return dbctx->fetch_key_id(dbctx, keyid, publickey, intrans);
280 }
281 #endif