2 * keyd.c - key retrieval daemon
4 * Jonathan McDowell <noodles@earth.li>
6 * Copyright 2004 Project Purple
15 #include <sys/select.h>
16 #include <sys/socket.h>
17 #include <sys/types.h>
21 #include "charfuncs.h"
26 #include "keystructs.h"
29 #include "onak-conf.h"
39 logthing(LOGTHING_CRITICAL,
40 "Failed to fork into background: %d (%s)",
45 logthing(LOGTHING_INFO, "Backgrounded as pid %d.", pid);
51 freopen("/dev/null", "r", stdin);
52 freopen("/dev/null", "w", stdout);
53 freopen("/dev/null", "w", stderr);
58 void iteratefunc(void *ctx, struct openpgp_publickey *key)
60 struct openpgp_packet_list *packets = NULL;
61 struct openpgp_packet_list *list_end = NULL;
62 struct buffer_ctx storebuf;
64 int *fd = (int *) ctx;
69 storebuf.buffer = malloc(8192);
71 logthing(LOGTHING_TRACE,
72 "Iterating over 0x%016" PRIX64 ".",
75 flatten_publickey(key,
78 write_openpgp_stream(buffer_putchar,
81 logthing(LOGTHING_TRACE,
84 ret = write(*fd, &storebuf.offset,
85 sizeof(storebuf.offset));
87 write(*fd, storebuf.buffer,
91 free(storebuf.buffer);
92 storebuf.buffer = NULL;
93 storebuf.size = storebuf.offset = 0;
94 free_packet_list(packets);
95 packets = list_end = NULL;
101 int sock_init(const char *sockname)
103 struct sockaddr_un sock;
107 fd = socket(PF_UNIX, SOCK_STREAM, 0);
109 ret = fcntl(fd, F_SETFD, 1);
113 sock.sun_family = AF_UNIX;
114 strncpy(sock.sun_path, sockname, sizeof(sock.sun_path) - 1);
116 ret = bind(fd, (struct sockaddr *) &sock, sizeof(sock));
128 uint32_t cmd = KEYD_CMD_UNKNOWN;
134 struct openpgp_publickey *key = NULL;
135 struct openpgp_packet_list *packets = NULL;
136 struct openpgp_packet_list *list_end = NULL;
137 struct buffer_ctx storebuf;
140 * Get the command from the client.
142 bytes = read(fd, &cmd, sizeof(cmd));
144 logthing(LOGTHING_DEBUG, "Read %d bytes, command: %d", bytes, cmd);
146 if (bytes != sizeof(cmd)) {
152 case KEYD_CMD_VERSION:
154 write(fd, &cmd, sizeof(cmd));
155 write(fd, &keyd_version, sizeof(keyd_version));
159 write(fd, &cmd, sizeof(cmd));
160 bytes = read(fd, &keyid, sizeof(keyid));
161 if (bytes != sizeof(keyid)) {
166 logthing(LOGTHING_INFO,
167 "Fetching 0x%" PRIX64
171 fetch_key(keyid, &key, false));
173 storebuf.size = 8192;
174 storebuf.buffer = malloc(8192);
176 flatten_publickey(key,
179 write_openpgp_stream(buffer_putchar,
182 logthing(LOGTHING_TRACE,
185 write(fd, &storebuf.offset,
186 sizeof(storebuf.offset));
187 write(fd, storebuf.buffer,
190 free(storebuf.buffer);
191 storebuf.buffer = NULL;
192 storebuf.size = storebuf.offset = 0;
193 free_packet_list(packets);
194 packets = list_end = NULL;
198 write(fd, &storebuf.offset,
199 sizeof(storebuf.offset));
203 case KEYD_CMD_GETTEXT:
205 write(fd, &cmd, sizeof(cmd));
206 bytes = read(fd, &count, sizeof(count));
207 if (bytes != sizeof(count)) {
212 search = malloc(count+1);
213 read(fd, search, count);
215 logthing(LOGTHING_INFO,
216 "Fetching %s, result: %d",
219 fetch_key_text(search, &key));
221 storebuf.size = 8192;
222 storebuf.buffer = malloc(8192);
224 flatten_publickey(key,
227 write_openpgp_stream(buffer_putchar,
230 logthing(LOGTHING_TRACE,
233 write(fd, &storebuf.offset,
234 sizeof(storebuf.offset));
235 write(fd, storebuf.buffer,
238 free(storebuf.buffer);
239 storebuf.buffer = NULL;
240 storebuf.size = storebuf.offset = 0;
241 free_packet_list(packets);
242 packets = list_end = NULL;
246 write(fd, &storebuf.offset,
247 sizeof(storebuf.offset));
253 write(fd, &cmd, sizeof(cmd));
255 bytes = read(fd, &storebuf.size,
256 sizeof(storebuf.size));
257 logthing(LOGTHING_TRACE, "Reading %d bytes.",
259 if (bytes != sizeof(storebuf.size)) {
262 if (ret == 0 && storebuf.size > 0) {
263 storebuf.buffer = malloc(storebuf.size);
265 while (bytes >= 0 && count < storebuf.size) {
267 &storebuf.buffer[count],
268 storebuf.size - count);
269 logthing(LOGTHING_TRACE,
274 read_openpgp_stream(buffer_fetchchar,
278 parse_keys(packets, &key);
279 config.dbbackend->store_key(key, false, false);
280 free_packet_list(packets);
284 free(storebuf.buffer);
285 storebuf.buffer = NULL;
286 storebuf.size = storebuf.offset = 0;
289 case KEYD_CMD_DELETE:
291 write(fd, &cmd, sizeof(cmd));
292 bytes = read(fd, &keyid, sizeof(keyid));
293 if (bytes != sizeof(keyid)) {
297 logthing(LOGTHING_INFO,
298 "Deleting 0x%" PRIX64
301 config.dbbackend->delete_key(
305 case KEYD_CMD_GETFULLKEYID:
307 write(fd, &cmd, sizeof(cmd));
308 bytes = read(fd, &keyid, sizeof(keyid));
309 if (bytes != sizeof(keyid)) {
313 keyid = config.dbbackend->getfullkeyid(keyid);
314 write(fd, &keyid, sizeof(keyid));
317 case KEYD_CMD_KEYITER:
319 write(fd, &cmd, sizeof(cmd));
320 config.dbbackend->iterate_keys(iteratefunc,
323 write(fd, &bytes, sizeof(bytes));
332 logthing(LOGTHING_ERROR, "Got unknown command: %d",
334 cmd = KEYD_REPLY_UNKNOWN_CMD;
335 write(fd, &cmd, sizeof(cmd));
342 int sock_close(int fd)
344 shutdown(fd, SHUT_RDWR);
348 int sock_accept(int fd)
350 struct sockaddr_un sock;
355 socklen = sizeof(sock);
356 srv = accept(fd, (struct sockaddr *) &sock, &socklen);
358 ret = fcntl(srv, F_SETFD, 1);
362 while (!sock_do(srv)) ;
369 int main(int argc, char *argv[])
374 char *configfile = NULL;
375 bool foreground = false;
378 while ((optchar = getopt(argc, argv, "c:f")) != -1 ) {
381 configfile = strdup(optarg);
389 readconfig(configfile);
392 initlogthing("keyd", config.logfile);
393 config.use_keyd = false;
401 snprintf(sockname, 1023, "%s/%s", config.db_dir, KEYD_SOCKET);
402 fd = sock_init(sockname);
408 config.dbbackend->initdb(false);
410 logthing(LOGTHING_NOTICE, "Accepting connections.");
411 while (!cleanup() && select(fd + 1, &rfds, NULL, NULL, NULL) != -1) {
412 logthing(LOGTHING_INFO, "Accepted connection.");
416 config.dbbackend->cleanupdb();
424 return(EXIT_SUCCESS);