First cut at cleanup infrastructure.
[onak.git] / gpgwww.c
1 /*
2  * gpgwww.c - www interface to path finder.
3  * 
4  * Jonathan McDowell <noodles@earth.li>
5  *
6  * Copyright 2001-2002 Project Purple.
7  */
8
9 #include <inttypes.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "armor.h"
15 #include "charfuncs.h"
16 #include "cleanup.h"
17 #include "getcgi.h"
18 #include "hash.h"
19 #include "keydb.h"
20 #include "log.h"
21 #include "mem.h"
22 #include "onak-conf.h"
23 #include "parsekey.h"
24 #include "stats.h"
25
26 #define OP_UNKNOWN 0
27 #define OP_GET     1
28
29 int parsecgistuff(char **cgiparams, uint64_t *from, uint64_t *to)
30 {
31         int i = 0;
32         int op = OP_UNKNOWN;
33
34         if (cgiparams != NULL) {
35                 i = 0;
36                 while (cgiparams[i] != NULL) {
37                         if (!strcmp(cgiparams[i], "to")) {
38                                 *to = strtoul(cgiparams[i+1], NULL, 16);
39                         } else if (!strcmp(cgiparams[i], "from")) {
40                                 *from = strtoul(cgiparams[i+1], NULL, 16);
41                         } else if (!strcmp(cgiparams[i], "op")) {
42                                 if (!strcmp(cgiparams[i+1], "get")) {
43                                         op = OP_GET;
44                                 }
45                         }
46                         i += 2;
47                 }
48         }
49
50         return op;
51 }
52
53 int getkeyspath(uint64_t have, uint64_t want, int count)
54 {
55         struct openpgp_publickey *publickey = NULL;
56         struct openpgp_packet_list *packets = NULL;
57         struct openpgp_packet_list *list_end = NULL;
58         struct stats_key *keyinfoa, *keyinfob, *curkey;
59         uint64_t fullhave, fullwant;
60         int rec;
61         int pathlen = 0;
62
63         fullhave = getfullkeyid(have);
64         fullwant = getfullkeyid(want);
65
66         /*
67          * Make sure the keys we have and want are in the cache.
68          */
69         cached_getkeysigs(fullhave);
70         cached_getkeysigs(fullwant);
71
72         if ((keyinfoa = findinhash(fullhave)) == NULL) {
73                 return 1;
74         }
75         if ((keyinfob = findinhash(fullwant)) == NULL) {
76                 return 1;
77         }
78         
79         while ((!cleanup()) && (pathlen < count)) {
80                 /*
81                  * Fill the tree info up.
82                  */
83                 initcolour(true);
84                 rec = findpath(keyinfoa, keyinfob);
85                 keyinfob->parent = 0;
86                 if (keyinfoa->colour == 0) {
87                         pathlen = count;
88                 } else {
89                         /*
90                          * Skip the first key, as the remote user will already
91                          * have it
92                          */
93                         curkey = findinhash(keyinfoa->parent);
94                         while (curkey != NULL && curkey->keyid != 0) {
95                                 if (curkey->keyid != fullwant && fetch_key(
96                                                 curkey->keyid,
97                                                         &publickey, false)) {
98                                         flatten_publickey(publickey,
99                                                         &packets,
100                                                         &list_end);
101                                         free_publickey(publickey);
102                                         publickey = NULL;
103                                 }
104                                 if (curkey != keyinfoa && curkey != keyinfob) {
105                                         curkey->disabled = true;
106                                 }
107                                 curkey = findinhash(curkey->parent);
108                         }
109                 }
110                 pathlen++;
111         }
112
113         /*
114          * Add the destination key to the list of returned keys.
115          */
116         if (fetch_key(fullwant, &publickey, false)) {
117                 flatten_publickey(publickey,
118                                 &packets,
119                                 &list_end);
120                 free_publickey(publickey);
121                 publickey = NULL;
122         }
123
124         armor_openpgp_stream(stdout_putchar, NULL, packets);
125         free_packet_list(packets);
126         packets = list_end = NULL;
127
128         return 0;
129 }
130
131 int main(int argc, char *argv[])
132 {
133         char     **cgiparams = NULL;    /* Our CGI parameter block */
134         uint64_t   from = 0, to = 0;
135         int        op = OP_UNKNOWN;
136
137         cgiparams = getcgivars(argc, argv);
138
139
140         op = parsecgistuff(cgiparams, &from, &to);
141         
142         if (op != OP_GET) {
143                 start_html("Experimental PGP key path finder results");
144         } else {
145                 puts("Content-Type: text/plain\n");
146         }
147
148         if (from == 0 || to == 0) {
149                 printf("Must pass from & to\n");
150                 puts("</HTML>");
151                 exit(1);
152         }
153
154         if (op != OP_GET) {
155                 printf("<P>Looking for path from 0x%llX to 0x%llX.\n",
156                                 from, to);
157                 printf("<A HREF=\"gpgwww?from=0x%08llX&to=0x%08llX\">"
158                                 "Find reverse path</A>\n",
159                                 to,
160                                 from);
161                 printf("<A HREF=\"gpgwww?from=0x%08llX&to=0x%08llX&op=get\">"
162                                 "Get all keys listed</A></P>\n",
163                                 from,
164                                 to);
165         }
166
167         readconfig(NULL);
168         initlogthing("gpgwww", config.logfile);
169         catchsignals();
170         initdb(true);
171         inithash();
172         logthing(LOGTHING_NOTICE, "Looking for path from 0x%llX to 0x%llX.",
173                         from,
174                         to);
175         if (op == OP_GET) {
176                 getkeyspath(from, to, 3);
177         } else {
178                 dofindpath(from, to, true, 3);
179         }
180         destroyhash();
181         cleanupdb();
182         cleanuplogthing();
183         cleanupconfig();
184
185         if (op != OP_GET) {
186                 puts("<HR>");
187                 puts("Produced by gpgwww " VERSION ", part of onak. "
188                         "<A HREF=\"mailto:noodles-onak@earth.li\">"
189                         "Jonathan McDowell</A>");
190                 end_html();
191         }
192
193         cleanupcgi(cgiparams);
194         cgiparams = NULL;
195
196         return EXIT_SUCCESS;
197 }