]> the.earth.li Git - onak.git/blob - lookup.c
Use dynamic context for all backend databases
[onak.git] / lookup.c
1 /*
2  * lookup.c - CGI to lookup keys.
3  *
4  * Copyright 2002-2005,2007-2009,2011 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 <inttypes.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "armor.h"
28 #include "charfuncs.h"
29 #include "cleankey.h"
30 #include "cleanup.h"
31 #include "getcgi.h"
32 #include "keydb.h"
33 #include "keyid.h"
34 #include "keyindex.h"
35 #include "log.h"
36 #include "mem.h"
37 #include "onak-conf.h"
38 #include "parsekey.h"
39 #include "photoid.h"
40 #include "version.h"
41
42 #define OP_UNKNOWN 0
43 #define OP_GET     1
44 #define OP_INDEX   2
45 #define OP_VINDEX  3
46 #define OP_PHOTO   4
47 #define OP_HGET    5
48
49 void find_keys(struct onak_dbctx *dbctx,
50                 char *search, uint64_t keyid, uint8_t *fp, size_t fpsize,
51                 bool ishex, bool isfp, bool fingerprint, bool skshash,
52                 bool exact, bool verbose, bool mrhkp)
53 {
54         struct openpgp_publickey *publickey = NULL;
55         int count = 0;
56
57         if (ishex) {
58                 count = dbctx->fetch_key_id(dbctx, keyid, &publickey,
59                                 false);
60         } else if (isfp) {
61                 count = dbctx->fetch_key_fp(dbctx, fp, fpsize, &publickey,
62                                 false);
63         } else {
64                 count = dbctx->fetch_key_text(dbctx, search, &publickey);
65         }
66         if (publickey != NULL) {
67                 if (mrhkp) {
68                         printf("info:1:%d\n", count);
69                         mrkey_index(publickey);
70                 } else {
71                         key_index(dbctx, publickey, verbose, fingerprint,
72                                 skshash, true);
73                 }
74                 free_publickey(publickey);
75         } else if (count == 0) {
76                 if (mrhkp) {
77                         puts("info:1:0");
78                 } else {
79                         puts("Key not found.");
80                 }
81         } else {
82                 if (mrhkp) {
83                         puts("info:1:0");
84                 } else {
85                         printf("Found %d keys, but maximum number to return"
86                                 " is %d.\n",
87                                 count,
88                                 config.maxkeys);
89                         puts("Try again with a more specific search.");
90                 }
91         }
92 }
93
94 static uint8_t hex2bin(char c)
95 {
96         if (c >= '0' && c <= '9') {
97                 return (c - '0');
98         } else if (c >= 'a' && c <= 'f') {
99                 return (c - 'a' + 10);
100         } else if (c >= 'A' && c <= 'F') {
101                 return (c - 'A' + 10);
102         }
103
104         return 255;
105 }
106
107 int main(int argc, char *argv[])
108 {
109         char **params = NULL;
110         int op = OP_UNKNOWN;
111         int i;
112         int indx = 0;
113         bool fingerprint = false;
114         bool skshash = false;
115         bool exact = false;
116         bool ishex = false;
117         bool isfp = false;
118         bool mrhkp = false;
119         uint64_t keyid = 0;
120         uint8_t fp[MAX_FINGERPRINT_LEN];
121         char *search = NULL;
122         char *end = NULL;
123         struct openpgp_publickey *publickey = NULL;
124         struct openpgp_packet_list *packets = NULL;
125         struct openpgp_packet_list *list_end = NULL;
126         int result;
127         struct skshash hash;
128         struct onak_dbctx *dbctx;
129
130         params = getcgivars(argc, argv);
131         for (i = 0; params != NULL && params[i] != NULL; i += 2) {
132                 if (!strcmp(params[i], "op")) {
133                         if (!strcmp(params[i+1], "get")) {
134                                 op = OP_GET;
135                         } else if (!strcmp(params[i+1], "hget")) {
136                                 op = OP_HGET;
137                         } else if (!strcmp(params[i+1], "index")) {
138                                 op = OP_INDEX;
139                         } else if (!strcmp(params[i+1], "vindex")) {
140                                 op = OP_VINDEX;
141                         } else if (!strcmp(params[i+1], "photo")) {
142                                 op = OP_PHOTO;
143                         }
144                 } else if (!strcmp(params[i], "search")) {
145                         search = params[i+1];
146                         params[i+1] = NULL;
147                         if (search != NULL && strlen(search) == 42 &&
148                                         search[0] == '0' && search[1] == 'x') {
149                                 for (i = 0; i < MAX_FINGERPRINT_LEN; i++) {
150                                         fp[i] = (hex2bin(search[2 + i * 2])
151                                                                 << 4) +
152                                                 hex2bin(search[3 + i * 2]);
153                                 }
154                                 isfp = true;
155                         } else if (search != NULL) {
156                                 keyid = strtoull(search, &end, 16);
157                                 if (*search != 0 &&
158                                                 end != NULL &&
159                                                 *end == 0) {
160                                         ishex = true;
161                                 }
162                         }
163                 } else if (!strcmp(params[i], "idx")) {
164                         indx = atoi(params[i+1]);
165                 } else if (!strcmp(params[i], "fingerprint")) {
166                         if (!strcmp(params[i+1], "on")) {
167                                 fingerprint = true;
168                         }
169                 } else if (!strcmp(params[i], "hash")) {
170                         if (!strcmp(params[i+1], "on")) {
171                                 skshash = true;
172                         }
173                 } else if (!strcmp(params[i], "exact")) {
174                         if (!strcmp(params[i+1], "on")) {
175                                 exact = true;
176                         }
177                 } else if (!strcmp(params[i], "options")) {
178                         /*
179                          * TODO: We should be smarter about this; options may
180                          * have several entries. For now mr is the only valid
181                          * one though.
182                          */
183                         if (!strcmp(params[i+1], "mr")) {
184                                 mrhkp = true;
185                         }
186                 }
187                 free(params[i]);
188                 params[i] = NULL;
189                 if (params[i+1] != NULL) {
190                         free(params[i+1]);
191                         params[i+1] = NULL;
192                 }
193         }
194         if (params != NULL) {
195                 free(params);
196                 params = NULL;
197         }
198
199         if (mrhkp) {
200                 puts("Content-Type: text/plain\n");
201         } else if (op == OP_PHOTO) {
202                 puts("Content-Type: image/jpeg\n");
203         } else {
204                 start_html("Lookup of key");
205         }
206
207         if (op == OP_UNKNOWN) {
208                 puts("Error: No operation supplied.");
209         } else if (search == NULL) {
210                 puts("Error: No key to search for supplied.");
211         } else {
212                 readconfig(NULL);
213                 initlogthing("lookup", config.logfile);
214                 catchsignals();
215                 dbctx = config.dbinit(false);
216                 switch (op) {
217                 case OP_GET:
218                 case OP_HGET:
219                         if (op == OP_HGET) {
220                                 parse_skshash(search, &hash);
221                                 result = dbctx->fetch_key_skshash(dbctx,
222                                         &hash, &publickey);
223                         } else if (ishex) {
224                                 result = dbctx->fetch_key_id(dbctx, keyid,
225                                         &publickey, false);
226                         } else if (isfp) {
227                                 result = dbctx->fetch_key_fp(dbctx, fp,
228                                         MAX_FINGERPRINT_LEN, &publickey, false);
229                         } else {
230                                 result = dbctx->fetch_key_text(dbctx,
231                                         search,
232                                         &publickey);
233                         }
234                         if (result) {
235                                 logthing(LOGTHING_NOTICE, 
236                                         "Found %d key(s) for search %s",
237                                         result,
238                                         search);
239                                 puts("<pre>");
240                                 cleankeys(publickey);
241                                 flatten_publickey(publickey,
242                                                         &packets,
243                                                         &list_end);
244                                 armor_openpgp_stream(stdout_putchar,
245                                                 NULL,
246                                                 packets);
247                                 puts("</pre>");
248                         } else {
249                                 logthing(LOGTHING_NOTICE,
250                                         "Failed to find key for search %s",
251                                         search);
252                                 puts("Key not found");
253                         }
254                         break;
255                 case OP_INDEX:
256                         find_keys(dbctx, search, keyid, fp, MAX_FINGERPRINT_LEN,
257                                         ishex, isfp, fingerprint, skshash,
258                                         exact, false, mrhkp);
259                         break;
260                 case OP_VINDEX:
261                         find_keys(dbctx, search, keyid, fp, MAX_FINGERPRINT_LEN,
262                                         ishex, isfp, fingerprint, skshash,
263                                         exact, true, mrhkp);
264                         break;
265                 case OP_PHOTO:
266                         if (isfp) {
267                                 dbctx->fetch_key_fp(dbctx, fp,
268                                         MAX_FINGERPRINT_LEN,
269                                         &publickey, false);
270                         } else {
271                                 dbctx->fetch_key_id(dbctx, keyid,
272                                         &publickey, false);
273                         }
274                         if (publickey != NULL) {
275                                 unsigned char *photo = NULL;
276                                 size_t         length = 0;
277
278                                 if (getphoto(publickey, indx, &photo,
279                                                 &length) == ONAK_E_OK) {
280                                         fwrite(photo,
281                                                         1,
282                                                         length,
283                                                         stdout);
284                                 }
285                                 free_publickey(publickey);
286                                 publickey = NULL;
287                         }
288                         break;
289                 default:
290                         puts("Unknown operation!");
291                 }
292                 dbctx->cleanupdb(dbctx);
293                 cleanuplogthing();
294                 cleanupconfig();
295         }
296         if (!mrhkp) {
297                 puts("<hr>");
298                 puts("Produced by onak " ONAK_VERSION );
299                 end_html();
300         }
301
302         if (search != NULL) {
303                 free(search);
304                 search = NULL;
305         }
306         
307         return (EXIT_SUCCESS);
308 }