Only seed initial Debian package database if key file is available.
[onak.git] / keydb_file.c
1 /*
2  * keydb.c - Routines to store and fetch keys.
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 #include <sys/types.h>
21 #include <sys/uio.h>
22 #include <dirent.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include "charfuncs.h"
31 #include "keydb.h"
32 #include "keyid.h"
33 #include "keystructs.h"
34 #include "ll.h"
35 #include "log.h"
36 #include "mem.h"
37 #include "onak-conf.h"
38 #include "parsekey.h"
39
40 /**
41  *      initdb - Initialize the key database.
42  *
43  *      This is just a no-op for flat file access.
44  */
45 static void file_initdb(bool readonly)
46 {
47 }
48
49 /**
50  *      cleanupdb - De-initialize the key database.
51  *
52  *      This is just a no-op for flat file access.
53  */
54 static void file_cleanupdb(void)
55 {
56 }
57
58 /**
59  *      starttrans - Start a transaction.
60  *
61  *      This is just a no-op for flat file access.
62  */
63 static bool file_starttrans(void)
64 {
65         return true;
66 }
67
68 /**
69  *      endtrans - End a transaction.
70  *
71  *      This is just a no-op for flat file access.
72  */
73 static void file_endtrans(void)
74 {
75         return;
76 }
77
78 /**
79  *      fetch_key - Given a keyid fetch the key from storage.
80  *      @keyid: The keyid to fetch.
81  *      @publickey: A pointer to a structure to return the key in.
82  *      @intrans: If we're already in a transaction.
83  *
84  *      We use the hex representation of the keyid as the filename to fetch the
85  *      key from. The key is stored in the file as a binary OpenPGP stream of
86  *      packets, so we can just use read_openpgp_stream() to read the packets
87  *      in and then parse_keys() to parse the packets into a publickey
88  *      structure.
89  */
90 static int file_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
91                 bool intrans)
92 {
93         struct openpgp_packet_list *packets = NULL;
94         char keyfile[1024];
95         int fd = -1;
96
97         snprintf(keyfile, 1023, "%s/0x%" PRIX64, config.db_dir,
98                         keyid & 0xFFFFFFFF);
99         fd = open(keyfile, O_RDONLY); // | O_SHLOCK);
100
101         if (fd > -1) {
102                 read_openpgp_stream(file_fetchchar, &fd, &packets, 0);
103                 parse_keys(packets, publickey);
104                 free_packet_list(packets);
105                 packets = NULL;
106                 close(fd);
107         }
108
109         return (fd > -1);
110 }
111
112 /**
113  *      store_key - Takes a key and stores it.
114  *      @publickey: A pointer to the public key to store.
115  *      @intrans: If we're already in a transaction.
116  *      @update: If true the key exists and should be updated.
117  *
118  *      Again we just use the hex representation of the keyid as the filename
119  *      to store the key to. We flatten the public key to a list of OpenPGP
120  *      packets and then use write_openpgp_stream() to write the stream out to
121  *      the file.
122  */
123 static int file_store_key(struct openpgp_publickey *publickey, bool intrans,
124                 bool update)
125 {
126         struct openpgp_packet_list *packets = NULL;
127         struct openpgp_packet_list *list_end = NULL;
128         struct openpgp_publickey *next = NULL;
129         char keyfile[1024];
130         int fd = -1;
131         uint64_t keyid;
132
133         get_keyid(publickey, &keyid);
134         snprintf(keyfile, 1023, "%s/0x%" PRIX64, config.db_dir,
135                         keyid & 0xFFFFFFFF);
136         fd = open(keyfile, O_WRONLY | O_CREAT, 0664); // | O_EXLOCK);
137
138         if (fd > -1) {
139                 next = publickey -> next;
140                 publickey -> next = NULL;
141                 flatten_publickey(publickey, &packets, &list_end);
142                 publickey -> next = next;
143                 
144                 write_openpgp_stream(file_putchar, &fd, packets);
145                 close(fd);
146                 free_packet_list(packets);
147                 packets = NULL;
148         }
149
150         return (fd > -1);
151 }
152
153 /**
154  *      delete_key - Given a keyid delete the key from storage.
155  *      @keyid: The keyid to delete.
156  *      @intrans: If we're already in a transaction.
157  *
158  *      This function deletes a public key from whatever storage mechanism we
159  *      are using. Returns 0 if the key existed.
160  */
161 static int file_delete_key(uint64_t keyid, bool intrans)
162 {
163         char keyfile[1024];
164
165         snprintf(keyfile, 1023, "%s/0x%" PRIX64, config.db_dir,
166                         keyid & 0xFFFFFFFF);
167
168         return unlink(keyfile);
169 }
170
171 /**
172  *      fetch_key_text - Trys to find the keys that contain the supplied text.
173  *      @search: The text to search for.
174  *      @publickey: A pointer to a structure to return the key in.
175  *
176  *      This function searches for the supplied text and returns the keys that
177  *      contain it.
178  *
179  *      TODO: Write for flat file access. Some sort of grep?
180  */
181 static int file_fetch_key_text(const char *search,
182                 struct openpgp_publickey **publickey)
183 {
184         return 0;
185 }
186
187 /**
188  *      iterate_keys - call a function once for each key in the db.
189  *      @iterfunc: The function to call.
190  *      @ctx: A context pointer
191  *
192  *      Calls iterfunc once for each key in the database. ctx is passed
193  *      unaltered to iterfunc. This function is intended to aid database dumps
194  *      and statistic calculations.
195  *
196  *      Returns the number of keys we iterated over.
197  */
198 static int file_iterate_keys(void (*iterfunc)(void *ctx,
199                 struct openpgp_publickey *key), void *ctx)
200 {
201         int                         numkeys = 0;
202         struct openpgp_packet_list *packets = NULL;
203         struct openpgp_publickey   *key = NULL;
204         DIR                        *dir;
205         char                        keyfile[1024];
206         int                         fd = -1;
207         struct dirent              *curfile = NULL;
208
209         dir = opendir(config.db_dir);
210
211         if (dir != NULL) {
212                 while ((curfile = readdir(dir)) != NULL) {
213                         if (curfile->d_name[0] == '0' &&
214                                         curfile->d_name[1] == 'x') {
215                                 snprintf(keyfile, 1023, "%s/%s",
216                                                 config.db_dir,
217                                                 curfile->d_name);
218                                 fd = open(keyfile, O_RDONLY);
219
220                                 if (fd > -1) {
221                                         read_openpgp_stream(file_fetchchar,
222                                                         &fd,
223                                                         &packets,
224                                                         0);
225                                         parse_keys(packets, &key);
226
227                                         iterfunc(ctx, key);
228
229                                         free_publickey(key);
230                                         key = NULL;
231                                         free_packet_list(packets);
232                                         packets = NULL;
233                                         close(fd);
234                                 }
235                                 numkeys++;
236                         }
237                 }
238                 
239                 closedir(dir);
240                 dir = NULL;
241         }
242
243         return numkeys;
244 }
245
246 /*
247  * Include the basic keydb routines.
248  */
249 #define NEED_KEYID2UID 1
250 #define NEED_GETKEYSIGS 1
251 #define NEED_GETFULLKEYID 1
252 #define NEED_UPDATEKEYS 1
253 #include "keydb.c"
254
255 struct dbfuncs keydb_file_funcs = {
256         .initdb                 = file_initdb,
257         .cleanupdb              = file_cleanupdb,
258         .starttrans             = file_starttrans,
259         .endtrans               = file_endtrans,
260         .fetch_key              = file_fetch_key,
261         .fetch_key_text         = file_fetch_key_text,
262         .store_key              = file_store_key,
263         .update_keys            = generic_update_keys,
264         .delete_key             = file_delete_key,
265         .getkeysigs             = generic_getkeysigs,
266         .cached_getkeysigs      = generic_cached_getkeysigs,
267         .keyid2uid              = generic_keyid2uid,
268         .getfullkeyid           = generic_getfullkeyid,
269         .iterate_keys           = file_iterate_keys,
270 };