Change to using Autoconf version string.
[onak.git] / onak.c
1 /*
2  * onak.c - An OpenPGP keyserver.
3  *
4  * This is the main swiss army knife binary.
5  *
6  * Jonathan McDowell <noodles@earth.li>
7  * 
8  * Copyright 2002 Project Purple
9  */
10
11 #include <getopt.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16
17 #include "armor.h"
18 #include "charfuncs.h"
19 #include "cleankey.h"
20 #include "cleanup.h"
21 #include "config.h"
22 #include "keydb.h"
23 #include "keyid.h"
24 #include "keyindex.h"
25 #include "keystructs.h"
26 #include "log.h"
27 #include "mem.h"
28 #include "merge.h"
29 #include "onak-conf.h"
30 #include "parsekey.h"
31 #include "photoid.h"
32
33 void find_keys(char *search, uint64_t keyid, bool ishex,
34                 bool fingerprint, bool exact, bool verbose)
35 {
36         struct openpgp_publickey *publickey = NULL;
37         int count = 0;
38
39         if (ishex) {
40                 count = fetch_key(keyid, &publickey, false);
41         } else {
42                 count = fetch_key_text(search, &publickey);
43         }
44         if (publickey != NULL) {
45                 key_index(publickey, verbose, fingerprint, false);
46                 free_publickey(publickey);
47         } else if (count == 0) {
48                 puts("Key not found.");
49         } else {
50                 printf("Found %d keys, but maximum number to return is %d.\n",
51                                 count,
52                                 config.maxkeys);
53                 puts("Try again with a more specific search.");
54         }
55 }
56
57 void usage(void) {
58         puts("onak " PACKAGE_VERSION " - an OpenPGP keyserver.\n");
59         puts("Usage:\n");
60         puts("\tonak [options] <command> <parameters>\n");
61         puts("\tCommands:\n");
62         puts("\tadd      - read armored OpenPGP keys from stdin and add to the"
63                 " keyserver");
64         puts("\tclean    - read armored OpenPGP keys from stdin, run the "
65                 " cleaning\n\t             routines against them and dump to"
66                 " stdout");
67         puts("\tdelete   - delete a given key from the keyserver");
68         puts("\tdump     - dump all the keys from the keyserver to a file or"
69                 " files\n\t           starting keydump*");
70         puts("\tget      - retrieves the key requested from the keyserver");
71         puts("\tgetphoto - retrieves the first photoid on the given key and"
72                 " dumps to\n\t           stdout");
73         puts("\tindex    - search for a key and list it");
74         puts("\tvindex   - search for a key and list it and its signatures");
75 }
76
77 int main(int argc, char *argv[])
78 {
79         struct openpgp_packet_list      *packets = NULL;
80         struct openpgp_packet_list      *list_end = NULL;
81         struct openpgp_publickey        *keys = NULL;
82         char                            *configfile = NULL;
83         int                              rc = EXIT_SUCCESS;
84         int                              result = 0;
85         char                            *search = NULL;
86         char                            *end = NULL;
87         uint64_t                         keyid = 0;
88         bool                             ishex = false;
89         bool                             verbose = false;
90         bool                             update = false;
91         bool                             binary = false;
92         bool                             fingerprint = false;
93         int                              optchar;
94
95         while ((optchar = getopt(argc, argv, "bc:fuv")) != -1 ) {
96                 switch (optchar) {
97                 case 'b': 
98                         binary = true;
99                         break;
100                 case 'c':
101                         configfile = strdup(optarg);
102                         break;
103                 case 'f': 
104                         fingerprint = true;
105                         break;
106                 case 'u': 
107                         update = true;
108                         break;
109                 case 'v': 
110                         verbose = true;
111                         setlogthreshold(LOGTHING_INFO);
112                         break;
113                 }
114         }
115
116         readconfig(configfile);
117         initlogthing("onak", config.logfile);
118         catchsignals();
119
120         if ((argc - optind) < 1) {
121                 usage();
122         } else if (!strcmp("dump", argv[optind])) {
123                 initdb(true);
124                 dumpdb("keydump");
125                 cleanupdb();
126         } else if (!strcmp("add", argv[optind])) {
127                 if (binary) {
128                         result = read_openpgp_stream(stdin_getchar, NULL,
129                                  &packets, 0);
130                         logthing(LOGTHING_INFO,
131                                         "read_openpgp_stream: %d", result);
132                 } else {
133                         dearmor_openpgp_stream(stdin_getchar, NULL, &packets);
134                 }
135                 if (packets != NULL) {
136                         result = parse_keys(packets, &keys);
137                         free_packet_list(packets);
138                         packets = NULL;
139                         logthing(LOGTHING_INFO, "Finished reading %d keys.",
140                                         result);
141
142                         result = cleankeys(keys);
143                         logthing(LOGTHING_INFO, "%d keys cleaned.",
144                                         result);
145
146                         initdb(false);
147                         logthing(LOGTHING_NOTICE, "Got %d new keys.",
148                                         update_keys(&keys));
149                         if (keys != NULL && update) {
150                                 flatten_publickey(keys,
151                                         &packets,
152                                         &list_end);
153                                 if (binary) {
154                                         write_openpgp_stream(stdout_putchar,
155                                                         NULL,
156                                                         packets);
157                                 } else {
158                                         armor_openpgp_stream(stdout_putchar,
159                                                 NULL,
160                                                 packets);
161                                 }
162                                 free_packet_list(packets);
163                                 packets = NULL;
164                         }
165                         cleanupdb();
166                 } else {
167                         rc = 1;
168                         logthing(LOGTHING_NOTICE, "No keys read.");
169                 }
170
171                 if (keys != NULL) {
172                         free_publickey(keys);
173                         keys = NULL;
174                 } else {
175                         rc = 1;
176                         logthing(LOGTHING_NOTICE, "No changes.");
177                 }
178         } else if (!strcmp("clean", argv[optind])) {
179                 if (binary) {
180                         result = read_openpgp_stream(stdin_getchar, NULL,
181                                  &packets, 0);
182                         logthing(LOGTHING_INFO,
183                                         "read_openpgp_stream: %d", result);
184                 } else {
185                         dearmor_openpgp_stream(stdin_getchar, NULL, &packets);
186                 }
187
188                 if (packets != NULL) {
189                         result = parse_keys(packets, &keys);
190                         free_packet_list(packets);
191                         packets = NULL;
192                         logthing(LOGTHING_INFO, "Finished reading %d keys.",
193                                         result);
194
195                         if (keys != NULL) {
196                                 result = cleankeys(keys);
197                                 logthing(LOGTHING_INFO, "%d keys cleaned.",
198                                                 result);
199
200                                 flatten_publickey(keys,
201                                         &packets,
202                                         &list_end);
203
204                                 if (binary) {
205                                         write_openpgp_stream(stdout_putchar,
206                                                         NULL,
207                                                         packets);
208                                 } else {
209                                         armor_openpgp_stream(stdout_putchar,
210                                                 NULL,
211                                                 packets);
212                                 }
213                                 free_packet_list(packets);
214                                 packets = NULL;
215                         }
216                 } else {
217                         rc = 1;
218                         logthing(LOGTHING_NOTICE, "No keys read.");
219                 }
220                 
221                 if (keys != NULL) {
222                         free_publickey(keys);
223                         keys = NULL;
224                 }
225         } else if ((argc - optind) == 2) {
226                 search = argv[optind+1];
227                 if (search != NULL) {
228                         keyid = strtoul(search, &end, 16);
229                         if (*search != 0 &&
230                                         end != NULL &&
231                                         *end == 0) {
232                                 ishex = true;
233                         }
234                 }
235                 initdb(false);
236                 if (!strcmp("index", argv[optind])) {
237                         find_keys(search, keyid, ishex, fingerprint,
238                                         false, false);
239                 } else if (!strcmp("vindex", argv[optind])) {
240                         find_keys(search, keyid, ishex, fingerprint,
241                                         false, true);
242                 } else if (!strcmp("getphoto", argv[optind])) {
243                         if (!ishex) {
244                                 puts("Can't get a key on uid text."
245                                         " You must supply a keyid.");
246                         } else if (fetch_key(keyid, &keys, false)) {
247                                 unsigned char *photo = NULL;
248                                 size_t         length = 0;
249
250                                 if (getphoto(keys, 0, &photo, &length)) {
251                                         fwrite(photo,
252                                                 1,
253                                                 length,
254                                                 stdout);
255                                 }
256                                 free_publickey(keys);
257                                 keys = NULL;
258                         } else {
259                                 puts("Key not found");
260                         }
261                 } else if (!strcmp("delete", argv[optind])) {
262                         delete_key(getfullkeyid(keyid), false);
263                 } else if (!strcmp("get", argv[optind])) {
264                         if (!ishex) {
265                                 puts("Can't get a key on uid text."
266                                         " You must supply a keyid.");
267                         } else if (fetch_key(keyid, &keys, false)) {
268                                 logthing(LOGTHING_INFO, "Got key.");
269                                 flatten_publickey(keys,
270                                                 &packets,
271                                                 &list_end);
272                                 free_publickey(keys);
273                                 armor_openpgp_stream(stdout_putchar,
274                                                 NULL,
275                                                 packets);
276                                 free_packet_list(packets);
277                                 packets = NULL;
278                         } else {
279                                 puts("Key not found");
280                         }
281                 }
282                 cleanupdb();
283         } else {
284                 usage();
285         }
286
287         cleanuplogthing();
288         cleanupconfig();
289
290         return rc;
291 }