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