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