1
/* gcryptrnd.c - Libgcrypt Random Number Daemon
2
* Copyright (C) 2006 Free Software Foundation, Inc.
4
* Gcryptend is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published
6
* by the Free Software Foundation; either version 2 of the License,
7
* or (at your option) any later version.
9
* Gcryptrnd is distributed in the hope that it will be useful, but
10
* WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
/* We require vsyslog pth
21
We need to test for: setrlimit
23
We should also prioritize requests. This is best done by putting
24
the requests into queues and have a main thread processing these
35
#include <sys/times.h>
36
#include <sys/types.h>
40
#include <sys/socket.h>
47
#define PGM "gcryptrnd"
48
#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION
49
#define BUGREPORT_LINE "\nReport bugs to <bug-libgcrypt@gnupg.org>.\n"
51
/* Pth wrapper function definitions. */
52
GCRY_THREAD_OPTION_PTH_IMPL;
55
/* Flag set to true if we have been daemonized. */
56
static int running_detached;
57
/* Flag indicating that a shutdown has been requested. */
58
static int shutdown_pending;
59
/* Counter for active connections. */
60
static int active_connections;
64
/* Local prototypes. */
65
static void serve (int listen_fd);
71
/* To avoid that a compiler optimizes certain memset calls away, these
72
macros may be used instead. */
73
#define wipememory2(_ptr,_set,_len) do { \
74
volatile char *_vptr=(volatile char *)(_ptr); \
75
size_t _vlen=(_len); \
76
while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
78
#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
83
/* Error printing utility. PRIORITY should be one of syslog's
84
priority levels. This fucntions prints to the stderro or syslog
85
depending on whether we are already daemonized. */
87
logit (int priority, const char *format, ...)
91
va_start (arg_ptr, format) ;
94
vsyslog (priority, format, arg_ptr);
98
fputs (PGM ": ", stderr);
99
vfprintf (stderr, format, arg_ptr);
105
/* Callback used by libgcrypt for logging. */
107
my_gcry_logger (void *dummy, int level, const char *format, va_list arg_ptr)
111
/* Map the log levels. */
114
case GCRY_LOG_CONT: level = LOG_INFO /* FIXME */; break;
115
case GCRY_LOG_INFO: level = LOG_INFO; break;
116
case GCRY_LOG_WARN: level = LOG_WARNING; break;
117
case GCRY_LOG_ERROR:level = LOG_ERR; break;
118
case GCRY_LOG_FATAL:level = LOG_CRIT; break;
119
case GCRY_LOG_BUG: level = LOG_CRIT; break;
120
case GCRY_LOG_DEBUG:level = LOG_DEBUG; break;
121
default: level = LOG_ERR; break;
123
if (running_detached)
125
vsyslog (level, format, arg_ptr);
129
fputs (PGM ": ", stderr);
130
vfprintf (stderr, format, arg_ptr);
131
if (!*format || format[strlen (format)-1] != '\n')
137
/* The cleanup handler - used to wipe out the secure memory. */
141
gcry_control (GCRYCTL_TERM_SECMEM );
145
/* Make us a daemon and open the syslog. */
155
if (pid == (pid_t)-1)
157
logit (LOG_CRIT, "fork failed: %s", strerror (errno));
165
logit (LOG_CRIT, "setsid() failed: %s", strerror(errno));
169
signal (SIGHUP, SIG_IGN);
172
if (pid == (pid_t)-1)
174
logit (LOG_CRIT, PGM ": second fork failed: %s", strerror (errno));
178
exit (0); /* First child exits. */
180
running_detached = 1;
184
logit (LOG_CRIT, "chdir(\"/\") failed: %s", strerror (errno));
189
for (i=0; i <= 2; i++)
192
openlog (PGM, LOG_PID, LOG_DAEMON);
197
disable_core_dumps (void)
199
#ifdef HAVE_SETRLIMIT
202
if (getrlimit (RLIMIT_CORE, &limit))
205
if( !setrlimit (RLIMIT_CORE, &limit) )
207
if (errno != EINVAL && errno != ENOSYS)
208
logit (LOG_ERR, "can't disable core dumps: %s\n", strerror (errno));
209
#endif /* HAVE_SETRLIMIT */
215
print_version (int with_help)
217
fputs (MYVERSION_LINE "\n"
218
"Copyright (C) 2006 Free Software Foundation, Inc.\n"
219
"License GPLv2+: GNU GPL version 2 or later "
220
"<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n"
221
"This is free software: you are free to change and redistribute it.\n"
222
"There is NO WARRANTY, to the extent permitted by law.\n",
227
"Usage: " PGM " [OPTIONS] [SOCKETNAME]\n"
228
"Start Libgcrypt's random number daemon listening"
229
" on socket SOCKETNAME\n"
230
"SOCKETNAME defaults to XXX\n"
232
" --no-detach do not deatach from the console\n"
233
" --version print version of the program and exit\n"
234
" --help display this help and exit\n"
235
BUGREPORT_LINE, stdout );
243
fputs ("usage: " PGM " [OPTIONS] [SOCKETNAME]\n", stderr);
244
fputs (" (use --help to display options)\n", stderr);
250
main (int argc, char **argv)
254
struct sockaddr_un *srvr_addr;
258
const char *socketname = "/var/run/libgcrypt/S.gcryptrnd";
265
while (argc && **argv == '-' && (*argv)[1] == '-')
272
else if (!strcmp (*argv, "--version"))
274
else if (!strcmp (*argv, "--help"))
276
else if (!strcmp (*argv, "--no-detach"))
286
socketname = argv[0];
293
signal (SIGPIPE, SIG_IGN);
295
logit (LOG_NOTICE, "started version " VERSION );
297
/* Libgcrypt requires us to register the threading model before we
298
do anything else with it. Note that this also calls pth_init. We
299
do the initialization while already running as a daemon to avoid
300
overhead with double initialization of Libgcrypt. */
301
err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
304
logit (LOG_CRIT, "can't register GNU Pth with Libgcrypt: %s",
309
/* Check that the libgcrypt version is sufficient. */
310
if (!gcry_check_version (VERSION) )
312
logit (LOG_CRIT, "libgcrypt is too old (need %s, have %s)",
313
VERSION, gcry_check_version (NULL) );
317
/* Register the logging callback and tell Libcgrypt to put the
318
random pool into secure memory. */
319
gcry_set_log_handler (my_gcry_logger, NULL);
320
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
322
/* Obviously we don't want to allow any core dumps. */
323
disable_core_dumps ();
325
/* Initialize the secure memory stuff which will also drop any extra
326
privileges we have. */
327
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
329
/* Register a cleanup handler. */
332
/* Create and listen on the socket. */
333
fd = socket (AF_UNIX, SOCK_STREAM, 0);
336
logit (LOG_CRIT, "can't create socket: %s", strerror (errno));
339
srvr_addr = gcry_xmalloc (sizeof *srvr_addr);
340
memset (srvr_addr, 0, sizeof *srvr_addr);
341
srvr_addr->sun_family = AF_UNIX;
342
if (strlen (socketname) + 1 >= sizeof (srvr_addr->sun_path))
344
logit (LOG_CRIT, "socket name `%s' too long", socketname);
347
strcpy (srvr_addr->sun_path, socketname);
348
addrlen = (offsetof (struct sockaddr_un, sun_path)
349
+ strlen (srvr_addr->sun_path) + 1);
350
rc = bind (fd, (struct sockaddr*) srvr_addr, addrlen);
351
if (rc == -1 && errno == EADDRINUSE)
354
rc = bind (fd, (struct sockaddr*) srvr_addr, addrlen);
358
logit (LOG_CRIT, "error binding socket to `%s': %s",
359
srvr_addr->sun_path, strerror (errno));
364
if (listen (fd, 5 ) == -1)
366
logit (LOG_CRIT, "listen() failed: %s", strerror (errno));
371
logit (LOG_INFO, "listening on socket `%s', fd=%d",
372
srvr_addr->sun_path, fd);
377
logit (LOG_NOTICE, "stopped version " VERSION );
382
/* Send LENGTH bytes of BUFFER to file descriptor FD. Returns 0 on
383
success or another value on write error. */
385
writen (int fd, const void *buffer, size_t length)
389
ssize_t n = pth_write (fd, buffer, length);
392
logit (LOG_ERR, "connection %d: write error: %s",
393
fd, strerror (errno));
394
return -1; /* write error */
397
buffer = (const char*)buffer + n;
403
/* Send an error response back. Returns 0 on success. */
405
send_error (int fd, int errcode)
407
unsigned char buf[2];
411
return writen (fd, buf, 2 );
414
/* Send a pong response back. Returns 0 on success or another value
419
return writen (fd, "\x00\x04pong", 6);
422
/* Send a nonce of size LENGTH back. Return 0 on success. */
424
send_nonce (int fd, int length)
426
unsigned char buf[2+255];
429
assert (length >= 0 && length <= 255);
432
gcry_create_nonce (buf+2, length);
433
rc = writen (fd, buf, 2+length );
434
wipememory (buf+2, length);
438
/* Send a random of size LENGTH with quality LEVEL back. Return 0 on
441
send_random (int fd, int length, int level)
443
unsigned char buf[2+255];
446
assert (length >= 0 && length <= 255);
447
assert (level == GCRY_STRONG_RANDOM || level == GCRY_VERY_STRONG_RANDOM);
450
/* Note that we don't bother putting the random stuff into secure
451
memory because this daemon is anyway intended to be run under
452
root and it is questionable whether the kernel buffers etc. are
453
equally well protected. */
454
gcry_randomize (buf+2, length, level);
455
rc = writen (fd, buf, 2+length );
456
wipememory (buf+2, length);
460
/* Main processing loop for a connection.
462
A request is made up of:
464
1 byte Total length of request; must be 3
469
12 = GetVeryStrongRandom
470
(all other values are reserved)
471
1 byte Number of requested bytes.
472
This is ignored for command Ping.
474
A response is made up of:
477
0 = Everything is fine
480
(For a bad request the connection will simply be closed)
481
1 byte Length of data
484
The requests are read as long as the connection is open.
489
connection_loop (int fd)
491
unsigned char request[3];
498
for (nleft=3, p=request; nleft > 0; )
500
n = pth_read (fd, p, nleft);
501
if (!n && p == request)
502
return; /* Client terminated connection. */
505
logit (LOG_ERR, "connection %d: read error: %s",
506
fd, n? strerror (errno) : "Unexpected EOF");
514
logit (LOG_ERR, "connection %d: invalid length (%d) of request",
524
case 10: /* GetNonce */
525
rc = send_nonce (fd, request[2]);
527
case 11: /* GetStrongRandom */
528
rc = send_random (fd, request[2], GCRY_STRONG_RANDOM);
530
case 12: /* GetVeryStrongRandom */
531
rc = send_random (fd, request[2], GCRY_VERY_STRONG_RANDOM);
534
default: /* Invalid command */
535
rc = send_error (fd, 1);
539
break; /* A write error occured while sending the response. */
545
/* Entry point for a connection's thread. */
547
connection_thread (void *arg)
551
active_connections++;
552
logit (LOG_INFO, "connection handler for fd %d started", fd);
554
connection_loop (fd);
557
logit (LOG_INFO, "connection handler for fd %d terminated", fd);
558
active_connections--;
564
/* This signal handler is called from the main loop between acepting
565
connections. It is called on the regular stack, thus no special
566
caution needs to be taken. It returns true to indicate that the
567
process should terminate. */
569
handle_signal (int signo)
574
logit (LOG_NOTICE, "SIGHUP received - re-reading configuration");
578
logit (LOG_NOTICE, "SIGUSR1 received - no action defined");
582
logit (LOG_NOTICE, "SIGUSR2 received - no action defined");
586
if (!shutdown_pending)
587
logit (LOG_NOTICE, "SIGTERM received - shutting down ...");
589
logit (LOG_NOTICE, "SIGTERM received - still %d active connections",
592
if (shutdown_pending > 2)
594
logit (LOG_NOTICE, "shutdown forced");
600
logit (LOG_NOTICE, "SIGINT received - immediate shutdown");
604
logit (LOG_NOTICE, "signal %d received - no action defined\n", signo);
611
/* Main server loop. This is called with the FD of the listening
614
serve (int listen_fd)
620
struct sockaddr_un paddr;
621
socklen_t plen = sizeof (paddr);
624
tattr = pth_attr_new();
625
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
626
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
627
pth_attr_set (tattr, PTH_ATTR_NAME, "connection");
630
sigaddset (&sigs, SIGHUP);
631
sigaddset (&sigs, SIGUSR1);
632
sigaddset (&sigs, SIGUSR2);
633
sigaddset (&sigs, SIGINT);
634
sigaddset (&sigs, SIGTERM);
635
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
639
if (shutdown_pending)
641
if (!active_connections)
644
/* Do not accept anymore connections but wait for existing
645
connections to terminate. */
648
if (pth_event_occurred (ev) && signo)
649
if (handle_signal (signo))
650
break; /* Stop the loop. */
654
gcry_fast_random_poll ();
655
fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev);
658
if (pth_event_occurred (ev))
660
if (handle_signal (signo))
661
break; /* Stop the loop. */
664
logit (LOG_WARNING, "accept failed: %s - waiting 1s\n",
666
gcry_fast_random_poll ();
671
if (!pth_spawn (tattr, connection_thread, (void*)fd))
673
logit (LOG_ERR, "error spawning connection handler: %s\n",
679
pth_event_free (ev, PTH_FREE_ALL);