Add /pks/hashquery
[onak.git] / hashquery.c
1 /*
2  * hashquery.c - CGI to handle SKS style /pks/hashquery requests
3  *
4  * Copyright 2011 Jonathan McDowell <noodles@earth.li>
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <stdint.h>
11 #include <unistd.h>
12
13 #include "charfuncs.h"
14 #include "cleanup.h"
15 #include "keyid.h"
16 #include "log.h"
17 #include "marshal.h"
18 #include "mem.h"
19 #include "onak-conf.h"
20
21 void doerror(char *error)
22 {
23         printf("Content-Type: text/plain\n\n");
24         printf("%s", error);
25         cleanuplogthing();
26         cleanupconfig();
27         exit(EXIT_FAILURE);
28 }
29
30 int main(int argc, char *argv[])
31 {
32         char *request_method;
33         int count, found, i;
34         uint8_t **hashes;
35         struct buffer_ctx cgipostbuf;
36         struct openpgp_publickey **keys;
37
38         readconfig(NULL);
39         initlogthing("hashquery", config.logfile);
40
41         request_method = getenv("REQUEST_METHOD");
42         if (request_method == NULL || strcmp(request_method, "POST") != 0) {
43                 doerror("hashquery must be a HTTP POST request.\n");
44         }
45
46         if (!(cgipostbuf.size = atoi(getenv("CONTENT_LENGTH")))) {
47                 doerror("Must provide a content length.\n");
48         }
49
50         cgipostbuf.offset = 0;
51         cgipostbuf.buffer = malloc(cgipostbuf.size);
52         if (cgipostbuf.buffer == NULL) {
53                 doerror("Couldn't allocate memory for query content.\n");
54         }
55
56         if (!fread(cgipostbuf.buffer, cgipostbuf.size, 1, stdin)) {
57                 doerror("Couldn't read query.\n");
58         }
59
60         hashes = (uint8_t **) unmarshal_array(buffer_fetchchar, &cgipostbuf,
61                         (void * (*)(int (*)(void *, size_t,  void *), void *))
62                                 unmarshal_skshash, &count);
63
64         free(cgipostbuf.buffer);
65         cgipostbuf.buffer = NULL;
66         cgipostbuf.size = cgipostbuf.offset = 0;
67
68         if (hashes == NULL) {
69                 doerror("No hashes supplied.\n");
70         }
71
72         found = 0;
73         keys = calloc(sizeof(struct openpgp_publickey *), count);
74         if (keys == NULL) {
75                 doerror("Couldn't allocate memory for reply.\n");
76         }
77
78         if (config.dbbackend->fetch_key_skshash == NULL) {
79                 doerror("Can't fetch by skshash with this backend.");
80         }
81
82         catchsignals();
83         config.dbbackend->initdb(false);
84
85         for (i = 0; i < count; i++) {
86                 config.dbbackend->fetch_key_skshash(
87                                 (struct skshash *) hashes[i], &keys[found]);
88                 if (keys[found] != NULL) {
89                         found++;
90                 }
91                 free(hashes[i]);
92                 hashes[i] = NULL;
93         }
94         free(hashes);
95         hashes = NULL;
96
97         config.dbbackend->cleanupdb();
98
99         puts("Content-Type: pgp/keys\n");
100         marshal_array(stdout_putchar, NULL,
101                         (void (*)(int (*)(void *, size_t,  void *),
102                                         void *, const void *))
103                                 marshal_publickey, (void **) keys, found);
104         printf("\n");
105
106         for (i = 0; i < found; i++) {
107                 free_publickey(keys[i]);
108         }
109         free(keys);
110
111         cleanuplogthing();
112         cleanupconfig();
113 }