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