]> git.sommitrealweird.co.uk Git - onak.git/blob - keydb.c
300e9b9a42690654e37b4649b1d06fbc70033c73
[onak.git] / keydb.c
1 /*
2  * keydb.c - Routines for DB access that just use store/fetch.
3  *
4  * Jonathan McDowell <noodles@earth.li>
5  *
6  * Copyright 2002-2004 Project Purple
7  */
8
9 /**
10  *      The routines in this file are meant to be used as an initial step when
11  *      adding a new db access module. They provide various functions required
12  *      of the db access module using only the store and fetch functions. As
13  *      they need to parse the actual OpenPGP data to work they are a lot
14  *      slower than custom functions however.
15  */
16
17 #include <stdio.h>
18
19 #include "decodekey.h"
20 #include "hash.h"
21 #include "keydb.h"
22 #include "keyid.h"
23 #include "keystructs.h"
24 #include "mem.h"
25 #include "merge.h"
26 #include "parsekey.h"
27 #include "sendsync.h"
28
29 #ifdef NEED_KEYID2UID
30 /**
31  *      keyid2uid - Takes a keyid and returns the primary UID for it.
32  *      @keyid: The keyid to lookup.
33  */
34 char *keyid2uid(uint64_t keyid)
35 {
36         struct openpgp_publickey *publickey = NULL;
37         struct openpgp_signedpacket_list *curuid = NULL;
38         char buf[1024];
39
40         buf[0]=0;
41         if (fetch_key(keyid, &publickey, false) && publickey != NULL) {
42                 curuid = publickey->uids;
43                 while (curuid != NULL && buf[0] == 0) {
44                         if (curuid->packet->tag == 13) {
45                                 snprintf(buf, 1023, "%.*s",
46                                                 (int) curuid->packet->length,
47                                                 curuid->packet->data);
48                         }
49                         curuid = curuid -> next;
50                 }
51                 free_publickey(publickey);
52         }
53
54         if (buf[0] == 0) {
55                 return NULL;
56         } else {
57                 return strdup(buf);
58         }
59 }
60 #endif
61
62 #ifdef NEED_GETKEYSIGS
63 /**
64  *      getkeysigs - Gets a linked list of the signatures on a key.
65  *      @keyid: The keyid to get the sigs for.
66  *      @revoked: Is the key revoked?
67  *
68  *      This function gets the list of signatures on a key. Used for key 
69  *      indexing and doing stats bits. If revoked is non-NULL then if the key
70  *      is revoked it's set to true.
71  */
72 struct ll *getkeysigs(uint64_t keyid, bool *revoked)
73 {
74         struct ll *sigs = NULL;
75         struct openpgp_signedpacket_list *uids = NULL;
76         struct openpgp_publickey *publickey = NULL;
77
78         fetch_key(keyid, &publickey, false);
79         
80         if (publickey != NULL) {
81                 for (uids = publickey->uids; uids != NULL; uids = uids->next) {
82                         sigs = keysigs(sigs, uids->sigs);
83                 }
84                 if (revoked != NULL) {
85                         *revoked = (publickey->revocations != NULL);
86                 }
87                 free_publickey(publickey);
88         }
89
90         return sigs;
91 }
92 #endif
93
94 /**
95  *      cached_getkeysigs - Gets the signatures on a key.
96  *      @keyid: The key we want the signatures for.
97  *      
98  *      This function gets the signatures on a key. It's the same as the
99  *      getkeysigs function above except we use the hash module to cache the
100  *      data so if we need it again it's already loaded.
101  */
102 struct ll *cached_getkeysigs(uint64_t keyid)
103 {
104         struct stats_key *key = NULL;
105         struct stats_key *signedkey = NULL;
106         struct ll        *cursig = NULL;
107         bool              revoked = false;
108
109         if (keyid == 0)  {
110                 return NULL;
111         }
112
113         key = createandaddtohash(keyid);
114
115         if (key->gotsigs == false) {
116                 key->sigs = getkeysigs(key->keyid, &revoked);
117                 key->revoked = revoked;
118                 for (cursig = key->sigs; cursig != NULL;
119                                 cursig = cursig->next) {
120                         signedkey = (struct stats_key *) cursig->object;
121                         signedkey->signs = lladd(signedkey->signs, key);
122                 }
123                 key->gotsigs = true;
124         }
125
126         return key->sigs;
127 }
128
129 #ifdef NEED_GETFULLKEYID
130 /**
131  *      getfullkeyid - Maps a 32bit key id to a 64bit one.
132  *      @keyid: The 32bit keyid.
133  *
134  *      This function maps a 32bit key id to the full 64bit one. It returns the
135  *      full keyid. If the key isn't found a keyid of 0 is returned.
136  */
137 uint64_t getfullkeyid(uint64_t keyid)
138 {
139         struct openpgp_publickey *publickey = NULL;
140
141         if (keyid < 0x100000000LL) {
142                 fetch_key(keyid, &publickey, false);
143                 if (publickey != NULL) {
144                         keyid = get_keyid(publickey);
145                         free_publickey(publickey);
146                         publickey = NULL;
147                 } else {
148                         keyid = 0;
149                 }
150         }
151         
152         return keyid;
153 }
154 #endif
155
156 #ifdef NEED_UPDATEKEYS
157 /**
158  *      update_keys - Takes a list of public keys and updates them in the DB.
159  *      @keys: The keys to update in the DB.
160  *      @sendsync: Should we send a sync mail to our peers.
161  *
162  *      Takes a list of keys and adds them to the database, merging them with
163  *      the key in the database if it's already present there. The key list is
164  *      update to contain the minimum set of updates required to get from what
165  *      we had before to what we have now (ie the set of data that was added to
166  *      the DB). Returns the number of entirely new keys added.
167  */
168 int update_keys(struct openpgp_publickey **keys, bool sendsync)
169 {
170         struct openpgp_publickey *curkey = NULL;
171         struct openpgp_publickey *oldkey = NULL;
172         struct openpgp_publickey *prev = NULL;
173         int newkeys = 0;
174         bool intrans;
175
176         for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
177                 intrans = starttrans();
178                 logthing(LOGTHING_INFO,
179                         "Fetching key 0x%llX, result: %d",
180                         get_keyid(curkey),
181                         fetch_key(get_keyid(curkey), &oldkey, intrans));
182
183                 /*
184                  * If we already have the key stored in the DB then merge it
185                  * with the new one that's been supplied. Otherwise the key
186                  * we've just got is the one that goes in the DB and also the
187                  * one that we send out.
188                  */
189                 if (oldkey != NULL) {
190                         merge_keys(oldkey, curkey);
191                         if (curkey->revocations == NULL &&
192                                         curkey->uids == NULL &&
193                                         curkey->subkeys == NULL) {
194                                 if (prev == NULL) {
195                                         *keys = curkey->next;
196                                 } else {
197                                         prev->next = curkey->next;
198                                         curkey->next = NULL;
199                                         free_publickey(curkey);
200                                         curkey = prev;
201                                 }
202                         } else {
203                                 prev = curkey;
204                                 logthing(LOGTHING_INFO,
205                                         "Merged key; storing updated key.");
206                                 store_key(oldkey, intrans, true);
207                         }
208                         free_publickey(oldkey);
209                         oldkey = NULL;
210                 } else {
211                         logthing(LOGTHING_INFO,
212                                 "Storing completely new key.");
213                         store_key(curkey, intrans, false);
214                         newkeys++;
215                 }
216                 endtrans();
217                 intrans = false;
218         }
219
220         if (sendsync && keys != NULL) {
221                 sendkeysync(*keys);
222         }
223
224         return newkeys;
225 }
226 #endif /* NEED_UPDATEKEYS */