]> git.sommitrealweird.co.uk Git - onak.git/blob - keydb_file.c
e1d0b528bc1f06eb08e3fdd473830603d82c1bcf
[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
132         snprintf(keyfile, 1023, "%s/0x%" PRIX64, config.db_dir,
133                         get_keyid(publickey) & 0xFFFFFFFF);
134         fd = open(keyfile, O_WRONLY | O_CREAT, 0664); // | O_EXLOCK);
135
136         if (fd > -1) {
137                 next = publickey -> next;
138                 publickey -> next = NULL;
139                 flatten_publickey(publickey, &packets, &list_end);
140                 publickey -> next = next;
141                 
142                 write_openpgp_stream(file_putchar, &fd, packets);
143                 close(fd);
144                 free_packet_list(packets);
145                 packets = NULL;
146         }
147
148         return (fd > -1);
149 }
150
151 /**
152  *      delete_key - Given a keyid delete the key from storage.
153  *      @keyid: The keyid to delete.
154  *      @intrans: If we're already in a transaction.
155  *
156  *      This function deletes a public key from whatever storage mechanism we
157  *      are using. Returns 0 if the key existed.
158  */
159 static int file_delete_key(uint64_t keyid, bool intrans)
160 {
161         char keyfile[1024];
162
163         snprintf(keyfile, 1023, "%s/0x%" PRIX64, config.db_dir,
164                         keyid & 0xFFFFFFFF);
165
166         return unlink(keyfile);
167 }
168
169 /**
170  *      fetch_key_text - Trys to find the keys that contain the supplied text.
171  *      @search: The text to search for.
172  *      @publickey: A pointer to a structure to return the key in.
173  *
174  *      This function searches for the supplied text and returns the keys that
175  *      contain it.
176  *
177  *      TODO: Write for flat file access. Some sort of grep?
178  */
179 static int file_fetch_key_text(const char *search,
180                 struct openpgp_publickey **publickey)
181 {
182         return 0;
183 }
184
185 /**
186  *      iterate_keys - call a function once for each key in the db.
187  *      @iterfunc: The function to call.
188  *      @ctx: A context pointer
189  *
190  *      Calls iterfunc once for each key in the database. ctx is passed
191  *      unaltered to iterfunc. This function is intended to aid database dumps
192  *      and statistic calculations.
193  *
194  *      Returns the number of keys we iterated over.
195  */
196 static int file_iterate_keys(void (*iterfunc)(void *ctx,
197                 struct openpgp_publickey *key), void *ctx)
198 {
199         int                         numkeys = 0;
200         struct openpgp_packet_list *packets = NULL;
201         struct openpgp_publickey   *key = NULL;
202         DIR                        *dir;
203         char                        keyfile[1024];
204         int                         fd = -1;
205         struct dirent              *curfile = NULL;
206
207         dir = opendir(config.db_dir);
208
209         if (dir != NULL) {
210                 while ((curfile = readdir(dir)) != NULL) {
211                         if (curfile->d_name[0] == '0' &&
212                                         curfile->d_name[1] == 'x') {
213                                 snprintf(keyfile, 1023, "%s/%s",
214                                                 config.db_dir,
215                                                 curfile->d_name);
216                                 fd = open(keyfile, O_RDONLY);
217
218                                 if (fd > -1) {
219                                         read_openpgp_stream(file_fetchchar,
220                                                         &fd,
221                                                         &packets,
222                                                         0);
223                                         parse_keys(packets, &key);
224
225                                         iterfunc(ctx, key);
226
227                                         free_publickey(key);
228                                         key = NULL;
229                                         free_packet_list(packets);
230                                         packets = NULL;
231                                         close(fd);
232                                 }
233                                 numkeys++;
234                         }
235                 }
236                 
237                 closedir(dir);
238                 dir = NULL;
239         }
240
241         return numkeys;
242 }
243
244 /*
245  * Include the basic keydb routines.
246  */
247 #define NEED_KEYID2UID 1
248 #define NEED_GETKEYSIGS 1
249 #define NEED_GETFULLKEYID 1
250 #define NEED_UPDATEKEYS 1
251 #include "keydb.c"
252
253 struct dbfuncs keydb_file_funcs = {
254         .initdb                 = file_initdb,
255         .cleanupdb              = file_cleanupdb,
256         .starttrans             = file_starttrans,
257         .endtrans               = file_endtrans,
258         .fetch_key              = file_fetch_key,
259         .fetch_key_text         = file_fetch_key_text,
260         .store_key              = file_store_key,
261         .update_keys            = generic_update_keys,
262         .delete_key             = file_delete_key,
263         .getkeysigs             = generic_getkeysigs,
264         .cached_getkeysigs      = generic_cached_getkeysigs,
265         .keyid2uid              = generic_keyid2uid,
266         .getfullkeyid           = generic_getfullkeyid,
267         .iterate_keys           = file_iterate_keys,
268 };