Add help text for keyd
[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 *generic_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 (config.dbbackend->fetch_key(keyid, &publickey, false) &&
42                         publickey != NULL) {
43                 curuid = publickey->uids;
44                 while (curuid != NULL && buf[0] == 0) {
45                         if (curuid->packet->tag == 13) {
46                                 snprintf(buf, 1023, "%.*s",
47                                                 (int) curuid->packet->length,
48                                                 curuid->packet->data);
49                         }
50                         curuid = curuid -> next;
51                 }
52                 free_publickey(publickey);
53         }
54
55         if (buf[0] == 0) {
56                 return NULL;
57         } else {
58                 return strdup(buf);
59         }
60 }
61 #endif
62
63 #ifdef NEED_GETKEYSIGS
64 /**
65  *      getkeysigs - Gets a linked list of the signatures on a key.
66  *      @keyid: The keyid to get the sigs for.
67  *      @revoked: Is the key revoked?
68  *
69  *      This function gets the list of signatures on a key. Used for key 
70  *      indexing and doing stats bits. If revoked is non-NULL then if the key
71  *      is revoked it's set to true.
72  */
73 struct ll *generic_getkeysigs(uint64_t keyid, bool *revoked)
74 {
75         struct ll *sigs = NULL;
76         struct openpgp_signedpacket_list *uids = NULL;
77         struct openpgp_publickey *publickey = NULL;
78
79         config.dbbackend->fetch_key(keyid, &publickey, false);
80         
81         if (publickey != NULL) {
82                 for (uids = publickey->uids; uids != NULL; uids = uids->next) {
83                         sigs = keysigs(sigs, uids->sigs);
84                 }
85                 if (revoked != NULL) {
86                         *revoked = publickey->revoked;
87                 }
88                 free_publickey(publickey);
89         }
90
91         return sigs;
92 }
93 #endif
94
95 /**
96  *      cached_getkeysigs - Gets the signatures on a key.
97  *      @keyid: The key we want the signatures for.
98  *      
99  *      This function gets the signatures on a key. It's the same as the
100  *      getkeysigs function above except we use the hash module to cache the
101  *      data so if we need it again it's already loaded.
102  */
103 struct ll *generic_cached_getkeysigs(uint64_t keyid)
104 {
105         struct stats_key *key = NULL;
106         struct stats_key *signedkey = NULL;
107         struct ll        *cursig = NULL;
108         struct ll        *sigs = NULL;
109         bool              revoked = false;
110
111         if (keyid == 0)  {
112                 return NULL;
113         }
114
115         key = findinhash(keyid);
116
117         if (key == NULL || key->gotsigs == false) {
118                 sigs = config.dbbackend->getkeysigs(keyid, &revoked);
119                 if (sigs == NULL) {
120                         return NULL;
121                 }
122                 if (key == NULL) {
123                         key = createandaddtohash(keyid);
124                 }
125                 key->sigs = sigs;
126                 key->revoked = revoked;
127                 for (cursig = key->sigs; cursig != NULL;
128                                 cursig = cursig->next) {
129                         signedkey = (struct stats_key *) cursig->object;
130                         signedkey->signs = lladd(signedkey->signs, key);
131                 }
132                 key->gotsigs = true;
133         }
134
135         return key->sigs;
136 }
137
138 #ifdef NEED_GETFULLKEYID
139 /**
140  *      getfullkeyid - Maps a 32bit key id to a 64bit one.
141  *      @keyid: The 32bit keyid.
142  *
143  *      This function maps a 32bit key id to the full 64bit one. It returns the
144  *      full keyid. If the key isn't found a keyid of 0 is returned.
145  */
146 uint64_t generic_getfullkeyid(uint64_t keyid)
147 {
148         struct openpgp_publickey *publickey = NULL;
149
150         if (keyid < 0x100000000LL) {
151                 config.dbbackend->fetch_key(keyid, &publickey, false);
152                 if (publickey != NULL) {
153                         keyid = get_keyid(publickey);
154                         free_publickey(publickey);
155                         publickey = NULL;
156                 } else {
157                         keyid = 0;
158                 }
159         }
160         
161         return keyid;
162 }
163 #endif
164
165 #ifdef NEED_UPDATEKEYS
166 /**
167  *      update_keys - Takes a list of public keys and updates them in the DB.
168  *      @keys: The keys to update in the DB.
169  *      @sendsync: Should we send a sync mail to our peers.
170  *
171  *      Takes a list of keys and adds them to the database, merging them with
172  *      the key in the database if it's already present there. The key list is
173  *      update to contain the minimum set of updates required to get from what
174  *      we had before to what we have now (ie the set of data that was added to
175  *      the DB). Returns the number of entirely new keys added.
176  */
177 int generic_update_keys(struct openpgp_publickey **keys, bool sendsync)
178 {
179         struct openpgp_publickey *curkey = NULL;
180         struct openpgp_publickey *oldkey = NULL;
181         struct openpgp_publickey *prev = NULL;
182         int newkeys = 0;
183         bool intrans;
184
185         for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
186                 intrans = config.dbbackend->starttrans();
187                 logthing(LOGTHING_INFO,
188                         "Fetching key 0x%" PRIX64 ", result: %d",
189                         get_keyid(curkey),
190                         config.dbbackend->fetch_key(get_keyid(curkey), &oldkey,
191                                         intrans));
192
193                 /*
194                  * If we already have the key stored in the DB then merge it
195                  * with the new one that's been supplied. Otherwise the key
196                  * we've just got is the one that goes in the DB and also the
197                  * one that we send out.
198                  */
199                 if (oldkey != NULL) {
200                         merge_keys(oldkey, curkey);
201                         if (curkey->sigs == NULL &&
202                                         curkey->uids == NULL &&
203                                         curkey->subkeys == NULL) {
204                                 if (prev == NULL) {
205                                         *keys = curkey->next;
206                                 } else {
207                                         prev->next = curkey->next;
208                                         curkey->next = NULL;
209                                         free_publickey(curkey);
210                                         curkey = prev;
211                                 }
212                         } else {
213                                 prev = curkey;
214                                 logthing(LOGTHING_INFO,
215                                         "Merged key; storing updated key.");
216                                 config.dbbackend->store_key(oldkey, intrans,
217                                         true);
218                         }
219                         free_publickey(oldkey);
220                         oldkey = NULL;
221                 } else {
222                         logthing(LOGTHING_INFO,
223                                 "Storing completely new key.");
224                         config.dbbackend->store_key(curkey, intrans, false);
225                         newkeys++;
226                 }
227                 config.dbbackend->endtrans();
228                 intrans = false;
229         }
230
231         if (sendsync && keys != NULL) {
232                 sendkeysync(*keys);
233         }
234
235         return newkeys;
236 }
237 #endif /* NEED_UPDATEKEYS */