]> the.earth.li Git - onak.git/blob - lookup.c
Add ability to drop overly large packets
[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, see <https://www.gnu.org/licenses/>.
17  */
18
19 #include <inttypes.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include "armor.h"
27 #include "charfuncs.h"
28 #include "cleankey.h"
29 #include "cleanup.h"
30 #include "getcgi.h"
31 #include "keydb.h"
32 #include "keyid.h"
33 #include "keyindex.h"
34 #include "log.h"
35 #include "mem.h"
36 #include "onak-conf.h"
37 #include "parsekey.h"
38 #include "photoid.h"
39 #include "version.h"
40
41 #define OP_UNKNOWN 0
42 #define OP_GET     1
43 #define OP_INDEX   2
44 #define OP_VINDEX  3
45 #define OP_PHOTO   4
46 #define OP_HGET    5
47
48 void find_keys(struct onak_dbctx *dbctx,
49                 char *search, uint64_t keyid,
50                 struct openpgp_fingerprint *fingerprint,
51                 bool ishex, bool isfp, bool dispfp, 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, fingerprint, &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, dispfp,
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, j;
112         int indx = 0;
113         bool dispfp = 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         struct openpgp_fingerprint fingerprint;
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                                 fingerprint.length = MAX_FINGERPRINT_LEN;
150                                 for (j = 0; j < MAX_FINGERPRINT_LEN; j++) {
151                                         fingerprint.fp[j] = (hex2bin(
152                                                         search[2 + j * 2])
153                                                                 << 4) +
154                                                 hex2bin(search[3 + j * 2]);
155                                 }
156                                 isfp = true;
157                         } else if (search != NULL) {
158                                 keyid = strtoull(search, &end, 16);
159                                 if (*search != 0 &&
160                                                 end != NULL &&
161                                                 *end == 0) {
162                                         ishex = true;
163                                 }
164                         }
165                 } else if (!strcmp(params[i], "idx")) {
166                         indx = atoi(params[i+1]);
167                 } else if (!strcmp(params[i], "fingerprint")) {
168                         if (!strcmp(params[i+1], "on")) {
169                                 dispfp = true;
170                         }
171                 } else if (!strcmp(params[i], "hash")) {
172                         if (!strcmp(params[i+1], "on")) {
173                                 skshash = true;
174                         }
175                 } else if (!strcmp(params[i], "exact")) {
176                         if (!strcmp(params[i+1], "on")) {
177                                 exact = true;
178                         }
179                 } else if (!strcmp(params[i], "options")) {
180                         /*
181                          * TODO: We should be smarter about this; options may
182                          * have several entries. For now mr is the only valid
183                          * one though.
184                          */
185                         if (!strcmp(params[i+1], "mr")) {
186                                 mrhkp = true;
187                         }
188                 }
189                 free(params[i]);
190                 params[i] = NULL;
191                 if (params[i+1] != NULL) {
192                         free(params[i+1]);
193                         params[i+1] = NULL;
194                 }
195         }
196         if (params != NULL) {
197                 free(params);
198                 params = NULL;
199         }
200
201         if (mrhkp) {
202                 puts("Content-Type: text/plain\n");
203         } else if (op == OP_PHOTO) {
204                 puts("Content-Type: image/jpeg\n");
205         } else {
206                 start_html("Lookup of key");
207         }
208
209         if (op == OP_UNKNOWN) {
210                 puts("Error: No operation supplied.");
211         } else if (search == NULL) {
212                 puts("Error: No key to search for supplied.");
213         } else {
214                 readconfig(NULL);
215                 initlogthing("lookup", config.logfile);
216                 catchsignals();
217                 dbctx = config.dbinit(config.backend, false);
218                 switch (op) {
219                 case OP_GET:
220                 case OP_HGET:
221                         if (op == OP_HGET) {
222                                 parse_skshash(search, &hash);
223                                 result = dbctx->fetch_key_skshash(dbctx,
224                                         &hash, &publickey);
225                         } else if (ishex) {
226                                 result = dbctx->fetch_key_id(dbctx, keyid,
227                                         &publickey, false);
228                         } else if (isfp) {
229                                 result = dbctx->fetch_key_fp(dbctx,
230                                         &fingerprint, &publickey, false);
231                         } else {
232                                 result = dbctx->fetch_key_text(dbctx,
233                                         search,
234                                         &publickey);
235                         }
236                         if (result) {
237                                 logthing(LOGTHING_NOTICE, 
238                                         "Found %d key(s) for search %s",
239                                         result,
240                                         search);
241                                 puts("<pre>");
242                                 cleankeys(&publickey, config.clean_policies);
243                                 flatten_publickey(publickey,
244                                                         &packets,
245                                                         &list_end);
246                                 armor_openpgp_stream(stdout_putchar,
247                                                 NULL,
248                                                 packets);
249                                 puts("</pre>");
250                         } else {
251                                 logthing(LOGTHING_NOTICE,
252                                         "Failed to find key for search %s",
253                                         search);
254                                 puts("Key not found");
255                         }
256                         break;
257                 case OP_INDEX:
258                         find_keys(dbctx, search, keyid, &fingerprint,
259                                         ishex, isfp, dispfp, skshash,
260                                         exact, false, mrhkp);
261                         break;
262                 case OP_VINDEX:
263                         find_keys(dbctx, search, keyid, &fingerprint,
264                                         ishex, isfp, dispfp, skshash,
265                                         exact, true, mrhkp);
266                         break;
267                 case OP_PHOTO:
268                         if (isfp) {
269                                 dbctx->fetch_key_fp(dbctx, &fingerprint,
270                                         &publickey, false);
271                         } else {
272                                 dbctx->fetch_key_id(dbctx, keyid,
273                                         &publickey, false);
274                         }
275                         if (publickey != NULL) {
276                                 unsigned char *photo = NULL;
277                                 size_t         length = 0;
278
279                                 if (getphoto(publickey, indx, &photo,
280                                                 &length) == ONAK_E_OK) {
281                                         fwrite(photo,
282                                                         1,
283                                                         length,
284                                                         stdout);
285                                 }
286                                 free_publickey(publickey);
287                                 publickey = NULL;
288                         }
289                         break;
290                 default:
291                         puts("Unknown operation!");
292                 }
293                 dbctx->cleanupdb(dbctx);
294                 cleanuplogthing();
295                 cleanupconfig();
296         }
297         if (!mrhkp) {
298                 puts("<hr>");
299                 puts("Produced by onak " ONAK_VERSION );
300                 end_html();
301         }
302
303         if (search != NULL) {
304                 free(search);
305                 search = NULL;
306         }
307         
308         return (EXIT_SUCCESS);
309 }