2 * keyd.c - key retrieval daemon
4 * Jonathan McDowell <noodles@earth.li>
6 * Copyright 2004 Project Purple
16 #include <sys/select.h>
17 #include <sys/socket.h>
18 #include <sys/types.h>
22 #include "charfuncs.h"
27 #include "keystructs.h"
30 #include "onak-conf.h"
40 logthing(LOGTHING_CRITICAL,
41 "Failed to fork into background: %d (%s)",
46 logthing(LOGTHING_INFO, "Backgrounded as pid %d.", pid);
52 freopen("/dev/null", "r", stdin);
53 freopen("/dev/null", "w", stdout);
54 freopen("/dev/null", "w", stderr);
59 void iteratefunc(void *ctx, struct openpgp_publickey *key)
61 struct openpgp_packet_list *packets = NULL;
62 struct openpgp_packet_list *list_end = NULL;
63 struct buffer_ctx storebuf;
65 int *fd = (int *) ctx;
70 storebuf.buffer = malloc(8192);
72 logthing(LOGTHING_TRACE,
73 "Iterating over 0x%016" PRIX64 ".",
76 flatten_publickey(key,
79 write_openpgp_stream(buffer_putchar,
82 logthing(LOGTHING_TRACE,
85 ret = write(*fd, &storebuf.offset,
86 sizeof(storebuf.offset));
88 write(*fd, storebuf.buffer,
92 free(storebuf.buffer);
93 storebuf.buffer = NULL;
94 storebuf.size = storebuf.offset = 0;
95 free_packet_list(packets);
96 packets = list_end = NULL;
102 int sock_init(const char *sockname)
104 struct sockaddr_un sock;
108 fd = socket(PF_UNIX, SOCK_STREAM, 0);
110 ret = fcntl(fd, F_SETFD, 1);
114 sock.sun_family = AF_UNIX;
115 strncpy(sock.sun_path, sockname, sizeof(sock.sun_path) - 1);
117 ret = bind(fd, (struct sockaddr *) &sock, sizeof(sock));
129 uint32_t cmd = KEYD_CMD_UNKNOWN;
135 struct openpgp_publickey *key = NULL;
136 struct openpgp_packet_list *packets = NULL;
137 struct openpgp_packet_list *list_end = NULL;
138 struct buffer_ctx storebuf;
141 * Get the command from the client.
143 bytes = read(fd, &cmd, sizeof(cmd));
145 logthing(LOGTHING_DEBUG, "Read %d bytes, command: %d", bytes, cmd);
147 if (bytes != sizeof(cmd)) {
153 case KEYD_CMD_VERSION:
155 write(fd, &cmd, sizeof(cmd));
156 cmd = sizeof(keyd_version);
157 write(fd, &cmd, sizeof(cmd));
158 write(fd, &keyd_version, sizeof(keyd_version));
162 write(fd, &cmd, sizeof(cmd));
163 bytes = read(fd, &keyid, sizeof(keyid));
164 if (bytes != sizeof(keyid)) {
169 logthing(LOGTHING_INFO,
170 "Fetching 0x%" PRIX64
174 fetch_key(keyid, &key, false));
176 storebuf.size = 8192;
177 storebuf.buffer = malloc(8192);
179 flatten_publickey(key,
182 write_openpgp_stream(buffer_putchar,
185 logthing(LOGTHING_TRACE,
188 write(fd, &storebuf.offset,
189 sizeof(storebuf.offset));
190 write(fd, storebuf.buffer,
193 free(storebuf.buffer);
194 storebuf.buffer = NULL;
195 storebuf.size = storebuf.offset = 0;
196 free_packet_list(packets);
197 packets = list_end = NULL;
201 write(fd, &storebuf.offset,
202 sizeof(storebuf.offset));
206 case KEYD_CMD_GETTEXT:
208 write(fd, &cmd, sizeof(cmd));
209 bytes = read(fd, &count, sizeof(count));
210 if (bytes != sizeof(count)) {
215 search = malloc(count+1);
216 read(fd, search, count);
218 logthing(LOGTHING_INFO,
219 "Fetching %s, result: %d",
222 fetch_key_text(search, &key));
224 storebuf.size = 8192;
225 storebuf.buffer = malloc(8192);
227 flatten_publickey(key,
230 write_openpgp_stream(buffer_putchar,
233 logthing(LOGTHING_TRACE,
236 write(fd, &storebuf.offset,
237 sizeof(storebuf.offset));
238 write(fd, storebuf.buffer,
241 free(storebuf.buffer);
242 storebuf.buffer = NULL;
243 storebuf.size = storebuf.offset = 0;
244 free_packet_list(packets);
245 packets = list_end = NULL;
249 write(fd, &storebuf.offset,
250 sizeof(storebuf.offset));
256 write(fd, &cmd, sizeof(cmd));
258 bytes = read(fd, &storebuf.size,
259 sizeof(storebuf.size));
260 logthing(LOGTHING_TRACE, "Reading %d bytes.",
262 if (bytes != sizeof(storebuf.size)) {
265 if (ret == 0 && storebuf.size > 0) {
266 storebuf.buffer = malloc(storebuf.size);
268 while (bytes >= 0 && count < storebuf.size) {
270 &storebuf.buffer[count],
271 storebuf.size - count);
272 logthing(LOGTHING_TRACE,
277 read_openpgp_stream(buffer_fetchchar,
281 parse_keys(packets, &key);
282 config.dbbackend->store_key(key, false, false);
283 free_packet_list(packets);
287 free(storebuf.buffer);
288 storebuf.buffer = NULL;
289 storebuf.size = storebuf.offset = 0;
292 case KEYD_CMD_DELETE:
294 write(fd, &cmd, sizeof(cmd));
295 bytes = read(fd, &keyid, sizeof(keyid));
296 if (bytes != sizeof(keyid)) {
300 logthing(LOGTHING_INFO,
301 "Deleting 0x%" PRIX64
304 config.dbbackend->delete_key(
308 case KEYD_CMD_GETFULLKEYID:
310 write(fd, &cmd, sizeof(cmd));
311 bytes = read(fd, &keyid, sizeof(keyid));
312 if (bytes != sizeof(keyid)) {
316 keyid = config.dbbackend->getfullkeyid(keyid);
318 write(fd, &cmd, sizeof(cmd));
319 write(fd, &keyid, sizeof(keyid));
322 case KEYD_CMD_KEYITER:
324 write(fd, &cmd, sizeof(cmd));
325 config.dbbackend->iterate_keys(iteratefunc,
328 write(fd, &bytes, sizeof(bytes));
332 write(fd, &cmd, sizeof(cmd));
337 write(fd, &cmd, sizeof(cmd));
338 logthing(LOGTHING_NOTICE,
339 "Exiting due to quit request.");
344 logthing(LOGTHING_ERROR, "Got unknown command: %d",
346 cmd = KEYD_REPLY_UNKNOWN_CMD;
347 write(fd, &cmd, sizeof(cmd));
354 int sock_close(int fd)
356 shutdown(fd, SHUT_RDWR);
360 int sock_accept(int fd)
362 struct sockaddr_un sock;
367 socklen = sizeof(sock);
368 srv = accept(fd, (struct sockaddr *) &sock, &socklen);
370 ret = fcntl(srv, F_SETFD, 1);
374 while (!sock_do(srv)) ;
381 int main(int argc, char *argv[])
386 char *configfile = NULL;
387 bool foreground = false;
390 while ((optchar = getopt(argc, argv, "c:f")) != -1 ) {
393 configfile = strdup(optarg);
401 readconfig(configfile);
404 initlogthing("keyd", config.logfile);
405 config.use_keyd = false;
412 signal(SIGPIPE, SIG_IGN);
414 snprintf(sockname, 1023, "%s/%s", config.db_dir, KEYD_SOCKET);
415 fd = sock_init(sockname);
421 config.dbbackend->initdb(false);
423 logthing(LOGTHING_NOTICE, "Accepting connections.");
424 while (!cleanup() && select(fd + 1, &rfds, NULL, NULL, NULL) != -1) {
425 logthing(LOGTHING_INFO, "Accepted connection.");
429 config.dbbackend->cleanupdb();
437 return(EXIT_SUCCESS);