spiped 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ext/spiped/extconf.rb +3 -0
- data/ext/spiped/spiped-source/BUILDING +46 -0
- data/ext/spiped/spiped-source/CHANGELOG +44 -0
- data/ext/spiped/spiped-source/COPYRIGHT +33 -0
- data/ext/spiped/spiped-source/Makefile +47 -0
- data/ext/spiped/spiped-source/Makefile.POSIX +27 -0
- data/ext/spiped/spiped-source/Makefile.inc +20 -0
- data/ext/spiped/spiped-source/Makefile.prog +23 -0
- data/ext/spiped/spiped-source/POSIX/README +10 -0
- data/ext/spiped/spiped-source/POSIX/posix-cflags.sh +10 -0
- data/ext/spiped/spiped-source/POSIX/posix-clock_realtime.c +3 -0
- data/ext/spiped/spiped-source/POSIX/posix-l.c +1 -0
- data/ext/spiped/spiped-source/POSIX/posix-l.sh +14 -0
- data/ext/spiped/spiped-source/POSIX/posix-msg_nosignal.c +3 -0
- data/ext/spiped/spiped-source/README +198 -0
- data/ext/spiped/spiped-source/STYLE +151 -0
- data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.c +464 -0
- data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.h +45 -0
- data/ext/spiped/spiped-source/libcperciva/alg/sha256.c +442 -0
- data/ext/spiped/spiped-source/libcperciva/alg/sha256.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c +13 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c +8 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport.sh +37 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport.h +63 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport_x86_aesni.c +30 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.c +166 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.h +31 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.c +229 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.h +31 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.c +124 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.h +41 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.c +293 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.h +43 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.c +46 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.h +9 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.c +215 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.c +21 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.c +276 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.h +167 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/mpool.h +85 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.c +334 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.h +89 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.c +241 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.h +60 -0
- data/ext/spiped/spiped-source/libcperciva/events/events.c +203 -0
- data/ext/spiped/spiped-source/libcperciva/events/events.h +106 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_immediate.c +149 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_internal.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_network.c +347 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_network_selectstats.c +106 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_timer.c +273 -0
- data/ext/spiped/spiped-source/libcperciva/network/network.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_accept.c +103 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_connect.c +258 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_read.c +155 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_write.c +188 -0
- data/ext/spiped/spiped-source/libcperciva/util/asprintf.c +49 -0
- data/ext/spiped/spiped-source/libcperciva/util/asprintf.h +16 -0
- data/ext/spiped/spiped-source/libcperciva/util/daemonize.c +134 -0
- data/ext/spiped/spiped-source/libcperciva/util/daemonize.h +10 -0
- data/ext/spiped/spiped-source/libcperciva/util/entropy.c +76 -0
- data/ext/spiped/spiped-source/libcperciva/util/entropy.h +13 -0
- data/ext/spiped/spiped-source/libcperciva/util/imalloc.h +33 -0
- data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.c +19 -0
- data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.h +33 -0
- data/ext/spiped/spiped-source/libcperciva/util/monoclock.c +52 -0
- data/ext/spiped/spiped-source/libcperciva/util/monoclock.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/noeintr.c +54 -0
- data/ext/spiped/spiped-source/libcperciva/util/noeintr.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock.c +472 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock.h +56 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_internal.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_util.c +271 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_util.h +51 -0
- data/ext/spiped/spiped-source/libcperciva/util/sysendian.h +146 -0
- data/ext/spiped/spiped-source/libcperciva/util/warnp.c +76 -0
- data/ext/spiped/spiped-source/libcperciva/util/warnp.h +59 -0
- data/ext/spiped/spiped-source/proto/proto_conn.c +362 -0
- data/ext/spiped/spiped-source/proto/proto_conn.h +25 -0
- data/ext/spiped/spiped-source/proto/proto_crypt.c +396 -0
- data/ext/spiped/spiped-source/proto/proto_crypt.h +102 -0
- data/ext/spiped/spiped-source/proto/proto_handshake.c +330 -0
- data/ext/spiped/spiped-source/proto/proto_handshake.h +30 -0
- data/ext/spiped/spiped-source/proto/proto_pipe.c +202 -0
- data/ext/spiped/spiped-source/proto/proto_pipe.h +23 -0
- data/ext/spiped/spiped-source/spipe/Makefile +90 -0
- data/ext/spiped/spiped-source/spipe/README +24 -0
- data/ext/spiped/spiped-source/spipe/main.c +178 -0
- data/ext/spiped/spiped-source/spipe/pushbits.c +101 -0
- data/ext/spiped/spiped-source/spipe/pushbits.h +10 -0
- data/ext/spiped/spiped-source/spipe/spipe.1 +60 -0
- data/ext/spiped/spiped-source/spiped/Makefile +98 -0
- data/ext/spiped/spiped-source/spiped/README +62 -0
- data/ext/spiped/spiped-source/spiped/dispatch.c +214 -0
- data/ext/spiped/spiped-source/spiped/dispatch.h +27 -0
- data/ext/spiped/spiped-source/spiped/main.c +267 -0
- data/ext/spiped/spiped-source/spiped/spiped.1 +112 -0
- data/lib/spiped.rb +3 -0
- metadata +143 -0
@@ -0,0 +1,188 @@
|
|
1
|
+
#include <sys/socket.h>
|
2
|
+
|
3
|
+
#include <assert.h>
|
4
|
+
#include <errno.h>
|
5
|
+
#include <limits.h>
|
6
|
+
#include <signal.h>
|
7
|
+
#include <stdint.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <unistd.h>
|
10
|
+
|
11
|
+
#include "events.h"
|
12
|
+
#include "warnp.h"
|
13
|
+
|
14
|
+
#include "network.h"
|
15
|
+
|
16
|
+
/**
|
17
|
+
* POSIX.1-2008 requires that MSG_NOSIGNAL be defined as a flag for send(2)
|
18
|
+
* which has the effect of preventing SIGPIPE from being raised when writing
|
19
|
+
* to a descriptor which has been shut down. Unfortunately there are some
|
20
|
+
* platforms which are not POSIX.1-2008 compliant; we provide a workaround
|
21
|
+
* (-DPOSIXFAIL_MSG_NOSIGNAL) which instead blocks the SIGPIPE signal on such
|
22
|
+
* platforms.
|
23
|
+
*
|
24
|
+
* (This workaround could be used automatically, but requiring that it be
|
25
|
+
* explicitly enabled helps to get platforms fixed.)
|
26
|
+
*/
|
27
|
+
#ifdef POSIXFAIL_MSG_NOSIGNAL
|
28
|
+
#ifndef MSG_NOSIGNAL
|
29
|
+
#define MSG_NOSIGNAL 0
|
30
|
+
#endif
|
31
|
+
#endif
|
32
|
+
|
33
|
+
struct network_write_cookie {
|
34
|
+
int (*callback)(void *, ssize_t);
|
35
|
+
void * cookie;
|
36
|
+
int fd;
|
37
|
+
const uint8_t * buf;
|
38
|
+
size_t buflen;
|
39
|
+
size_t minlen;
|
40
|
+
size_t bufpos;
|
41
|
+
};
|
42
|
+
|
43
|
+
/* Invoke the callback, clean up, and return the callback's status. */
|
44
|
+
static int
|
45
|
+
docallback(struct network_write_cookie * C, ssize_t nbytes)
|
46
|
+
{
|
47
|
+
int rc;
|
48
|
+
|
49
|
+
/* Invoke the callback. */
|
50
|
+
rc = (C->callback)(C->cookie, nbytes);
|
51
|
+
|
52
|
+
/* Clean up. */
|
53
|
+
free(C);
|
54
|
+
|
55
|
+
/* Return the callback's status. */
|
56
|
+
return (rc);
|
57
|
+
}
|
58
|
+
|
59
|
+
/* The socket is ready for reading/writing. */
|
60
|
+
static int
|
61
|
+
callback_buf(void * cookie)
|
62
|
+
{
|
63
|
+
struct network_write_cookie * C = cookie;
|
64
|
+
size_t oplen;
|
65
|
+
ssize_t len;
|
66
|
+
#ifdef POSIXFAIL_MSG_NOSIGNAL
|
67
|
+
void (*oldsig)(int);
|
68
|
+
#endif
|
69
|
+
|
70
|
+
/* If we don't have MSG_NOSIGNAL, catch SIGPIPE. */
|
71
|
+
#ifdef POSIXFAIL_MSG_NOSIGNAL
|
72
|
+
if ((oldsig = signal(SIGPIPE, SIG_IGN)) == SIG_ERR) {
|
73
|
+
warnp("signal(SIGPIPE)");
|
74
|
+
goto failed;
|
75
|
+
}
|
76
|
+
#endif
|
77
|
+
|
78
|
+
/* Attempt to read/write data to/from the buffer. */
|
79
|
+
oplen = C->buflen - C->bufpos;
|
80
|
+
len = send(C->fd, C->buf + C->bufpos, oplen, MSG_NOSIGNAL);
|
81
|
+
|
82
|
+
/* We should never see a send length of zero. */
|
83
|
+
assert(len != 0);
|
84
|
+
|
85
|
+
/* If we set a SIGPIPE handler, restore the old one. */
|
86
|
+
#ifdef POSIXFAIL_MSG_NOSIGNAL
|
87
|
+
if (signal(SIGPIPE, oldsig) == SIG_ERR) {
|
88
|
+
warnp("signal(SIGPIPE)");
|
89
|
+
goto failed;
|
90
|
+
}
|
91
|
+
#endif
|
92
|
+
|
93
|
+
/* Failure? */
|
94
|
+
if (len == -1) {
|
95
|
+
/* Was it really an error, or just a try-again? */
|
96
|
+
if ((errno == EAGAIN) ||
|
97
|
+
(errno == EWOULDBLOCK) ||
|
98
|
+
(errno == EINTR))
|
99
|
+
goto tryagain;
|
100
|
+
|
101
|
+
/* Something went wrong. */
|
102
|
+
goto failed;
|
103
|
+
}
|
104
|
+
|
105
|
+
/* We processed some data. Do we need to keep going? */
|
106
|
+
if ((C->bufpos += len) < C->minlen)
|
107
|
+
goto tryagain;
|
108
|
+
|
109
|
+
/* Invoke the callback and return. */
|
110
|
+
return (docallback(C, C->bufpos));
|
111
|
+
|
112
|
+
tryagain:
|
113
|
+
/* Reset the event. */
|
114
|
+
if (events_network_register(callback_buf, C, C->fd,
|
115
|
+
EVENTS_NETWORK_OP_WRITE))
|
116
|
+
goto failed;
|
117
|
+
|
118
|
+
/* Callback was reset. */
|
119
|
+
return (0);
|
120
|
+
|
121
|
+
failed:
|
122
|
+
/* Invoke the callback with a failure status and return. */
|
123
|
+
return (docallback(C, -1));
|
124
|
+
}
|
125
|
+
|
126
|
+
/**
|
127
|
+
* network_write(fd, buf, buflen, minwrite, callback, cookie):
|
128
|
+
* Asynchronously write up to ${buflen} bytes of data from ${buf} to ${fd}.
|
129
|
+
* When at least ${minwrite} bytes have been written or on error, invoke
|
130
|
+
* ${callback}(${cookie}, lenwrit), where lenwrit is -1 on error and the
|
131
|
+
* number of bytes written (between ${minwrite} and ${buflen} inclusive)
|
132
|
+
* otherwise. Return a cookie which can be passed to network_write_cancel in
|
133
|
+
* order to cancel the write.
|
134
|
+
*/
|
135
|
+
void *
|
136
|
+
network_write(int fd, const uint8_t * buf, size_t buflen, size_t minwrite,
|
137
|
+
int (* callback)(void *, ssize_t), void * cookie)
|
138
|
+
{
|
139
|
+
struct network_write_cookie * C;
|
140
|
+
|
141
|
+
/* Make sure buflen is non-zero. */
|
142
|
+
assert(buflen != 0);
|
143
|
+
|
144
|
+
/* Sanity-check: # bytes must fit into a ssize_t. */
|
145
|
+
assert(buflen <= SSIZE_MAX);
|
146
|
+
|
147
|
+
/* Bake a cookie. */
|
148
|
+
if ((C = malloc(sizeof(struct network_write_cookie))) == NULL)
|
149
|
+
goto err0;
|
150
|
+
C->callback = callback;
|
151
|
+
C->cookie = cookie;
|
152
|
+
C->fd = fd;
|
153
|
+
C->buf = buf;
|
154
|
+
C->buflen = buflen;
|
155
|
+
C->minlen = minwrite;
|
156
|
+
C->bufpos = 0;
|
157
|
+
|
158
|
+
/* Register a callback for network readiness. */
|
159
|
+
if (events_network_register(callback_buf, C, C->fd,
|
160
|
+
EVENTS_NETWORK_OP_WRITE))
|
161
|
+
goto err1;
|
162
|
+
|
163
|
+
/* Success! */
|
164
|
+
return (C);
|
165
|
+
|
166
|
+
err1:
|
167
|
+
free(C);
|
168
|
+
err0:
|
169
|
+
/* Failure! */
|
170
|
+
return (NULL);
|
171
|
+
}
|
172
|
+
|
173
|
+
/**
|
174
|
+
* network_write_cancel(cookie):
|
175
|
+
* Cancel the buffer write for which the cookie ${cookie} was returned by
|
176
|
+
* network_write. Do not invoke the callback associated with the write.
|
177
|
+
*/
|
178
|
+
void
|
179
|
+
network_write_cancel(void * cookie)
|
180
|
+
{
|
181
|
+
struct network_write_cookie * C = cookie;
|
182
|
+
|
183
|
+
/* Kill the network event. */
|
184
|
+
events_network_cancel(C->fd, EVENTS_NETWORK_OP_WRITE);
|
185
|
+
|
186
|
+
/* Free the cookie. */
|
187
|
+
free(C);
|
188
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#include <stdarg.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
#include <stdlib.h>
|
4
|
+
|
5
|
+
#include "asprintf.h"
|
6
|
+
|
7
|
+
/**
|
8
|
+
* asprintf(ret, format, ...):
|
9
|
+
* Do asprintf(3) like GNU and BSD do.
|
10
|
+
*/
|
11
|
+
int
|
12
|
+
asprintf(char ** ret, const char * format, ...)
|
13
|
+
{
|
14
|
+
va_list ap;
|
15
|
+
int len;
|
16
|
+
size_t buflen;
|
17
|
+
|
18
|
+
/* Figure out how long the string needs to be. */
|
19
|
+
va_start(ap, format);
|
20
|
+
len = vsnprintf(NULL, 0, format, ap);
|
21
|
+
va_end(ap);
|
22
|
+
|
23
|
+
/* Did we fail? */
|
24
|
+
if (len < 0)
|
25
|
+
goto err0;
|
26
|
+
buflen = (size_t)(len) + 1;
|
27
|
+
|
28
|
+
/* Allocate memory. */
|
29
|
+
if ((*ret = malloc(buflen)) == NULL)
|
30
|
+
goto err0;
|
31
|
+
|
32
|
+
/* Actually generate the string. */
|
33
|
+
va_start(ap, format);
|
34
|
+
len = vsnprintf(*ret, buflen, format, ap);
|
35
|
+
va_end(ap);
|
36
|
+
|
37
|
+
/* Did we fail? */
|
38
|
+
if (len < 0)
|
39
|
+
goto err1;
|
40
|
+
|
41
|
+
/* Success! */
|
42
|
+
return (len);
|
43
|
+
|
44
|
+
err1:
|
45
|
+
free(*ret);
|
46
|
+
err0:
|
47
|
+
/* Failure! */
|
48
|
+
return (-1);
|
49
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#ifndef _ASPRINTF_H_
|
2
|
+
#define _ASPRINTF_H_
|
3
|
+
|
4
|
+
/* Avoid namespace collisions with BSD/GNU asprintf. */
|
5
|
+
#ifdef asprintf
|
6
|
+
#undef asprintf
|
7
|
+
#endif
|
8
|
+
#define asprintf libcperciva_asprintf
|
9
|
+
|
10
|
+
/**
|
11
|
+
* asprintf(ret, format, ...):
|
12
|
+
* Do asprintf(3) like GNU and BSD do.
|
13
|
+
*/
|
14
|
+
int asprintf(char **, const char *, ...);
|
15
|
+
|
16
|
+
#endif /* !_ASPRINTF_H_ */
|
@@ -0,0 +1,134 @@
|
|
1
|
+
#include <errno.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
#include <unistd.h>
|
4
|
+
|
5
|
+
#include "noeintr.h"
|
6
|
+
#include "warnp.h"
|
7
|
+
|
8
|
+
#include "daemonize.h"
|
9
|
+
|
10
|
+
/**
|
11
|
+
* daemonize(spid):
|
12
|
+
* Daemonize and write the process ID in decimal to a file named ${spid}.
|
13
|
+
* The parent process will exit only after the child has written its pid.
|
14
|
+
* On success, the child will return 0; on failure, the parent will return
|
15
|
+
* -1.
|
16
|
+
*/
|
17
|
+
int
|
18
|
+
daemonize(const char * spid)
|
19
|
+
{
|
20
|
+
FILE * f;
|
21
|
+
int fd[2];
|
22
|
+
char dummy = 0;
|
23
|
+
|
24
|
+
/*
|
25
|
+
* Create a pipe for the child to notify the parent when it has
|
26
|
+
* finished daemonizing.
|
27
|
+
*/
|
28
|
+
if (pipe(fd)) {
|
29
|
+
warnp("pipe");
|
30
|
+
goto err0;
|
31
|
+
}
|
32
|
+
|
33
|
+
/*
|
34
|
+
* Fork into the parent process (which waits for a poke and exits)
|
35
|
+
* and the child process (which keeps going).
|
36
|
+
*/
|
37
|
+
switch (fork()) {
|
38
|
+
case -1:
|
39
|
+
/* Fork failed. */
|
40
|
+
warnp("fork");
|
41
|
+
goto err2;
|
42
|
+
case 0:
|
43
|
+
/* In child process. */
|
44
|
+
break;
|
45
|
+
default:
|
46
|
+
/*
|
47
|
+
* In parent process. Close write end of pipe so that if the
|
48
|
+
* client dies we will notice the pipe being reset.
|
49
|
+
*/
|
50
|
+
while (close(fd[1])) {
|
51
|
+
if (errno == EINTR)
|
52
|
+
continue;
|
53
|
+
warnp("close");
|
54
|
+
goto err1;
|
55
|
+
}
|
56
|
+
do {
|
57
|
+
switch (read(fd[0], &dummy, 1)) {
|
58
|
+
case -1:
|
59
|
+
/* Error in read. */
|
60
|
+
break;
|
61
|
+
case 0:
|
62
|
+
/* EOF -- the child died without poking us. */
|
63
|
+
goto err1;
|
64
|
+
case 1:
|
65
|
+
/* We have been poked by the child. Exit. */
|
66
|
+
_exit(0);
|
67
|
+
}
|
68
|
+
|
69
|
+
/* Anything other than EINTR is bad. */
|
70
|
+
if (errno != EINTR) {
|
71
|
+
warnp("read");
|
72
|
+
goto err1;
|
73
|
+
}
|
74
|
+
} while (1);
|
75
|
+
}
|
76
|
+
|
77
|
+
/* Set ourselves to be a session leader. */
|
78
|
+
if (setsid() == -1) {
|
79
|
+
warnp("setsid");
|
80
|
+
goto die;
|
81
|
+
}
|
82
|
+
|
83
|
+
/* Write out our pid file. */
|
84
|
+
if ((f = fopen(spid, "w")) == NULL) {
|
85
|
+
warnp("fopen(%s)", spid);
|
86
|
+
goto die;
|
87
|
+
}
|
88
|
+
if (fprintf(f, "%d", getpid()) < 0) {
|
89
|
+
warnp("fprintf");
|
90
|
+
goto die;
|
91
|
+
}
|
92
|
+
if (fclose(f)) {
|
93
|
+
warnp("fclose");
|
94
|
+
goto die;
|
95
|
+
}
|
96
|
+
|
97
|
+
/* Tell the parent to suicide. */
|
98
|
+
if (noeintr_write(fd[1], &dummy, 1) == -1) {
|
99
|
+
warnp("write");
|
100
|
+
goto die;
|
101
|
+
}
|
102
|
+
|
103
|
+
/* Close the pipe. */
|
104
|
+
while (close(fd[0])) {
|
105
|
+
if (errno == EINTR)
|
106
|
+
continue;
|
107
|
+
warnp("close");
|
108
|
+
goto die;
|
109
|
+
}
|
110
|
+
while (close(fd[1])) {
|
111
|
+
if (errno == EINTR)
|
112
|
+
continue;
|
113
|
+
warnp("close");
|
114
|
+
goto die;
|
115
|
+
}
|
116
|
+
|
117
|
+
/* Success! */
|
118
|
+
return (0);
|
119
|
+
|
120
|
+
err2:
|
121
|
+
close(fd[1]);
|
122
|
+
err1:
|
123
|
+
close(fd[0]);
|
124
|
+
err0:
|
125
|
+
/* Failure! */
|
126
|
+
return (-1);
|
127
|
+
|
128
|
+
die:
|
129
|
+
/*
|
130
|
+
* We're in the child and something bad happened; the parent will be
|
131
|
+
* notified when we die thanks to the pipe being closed.
|
132
|
+
*/
|
133
|
+
_exit(0);
|
134
|
+
}
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#include <fcntl.h>
|
2
|
+
#include <limits.h>
|
3
|
+
#include <stdint.h>
|
4
|
+
#include <unistd.h>
|
5
|
+
|
6
|
+
#include "warnp.h"
|
7
|
+
|
8
|
+
#include "entropy.h"
|
9
|
+
|
10
|
+
/**
|
11
|
+
* XXX Portability
|
12
|
+
* XXX We obtain random bytes from the operating system by opening
|
13
|
+
* XXX /dev/urandom and reading them from that device; this works on
|
14
|
+
* XXX modern UNIX-like operating systems but not on systems like
|
15
|
+
* XXX win32 where there is no concept of /dev/urandom.
|
16
|
+
*/
|
17
|
+
|
18
|
+
/**
|
19
|
+
* entropy_read(buf, buflen):
|
20
|
+
* Fill the given buffer with random bytes provided by the operating system.
|
21
|
+
*/
|
22
|
+
int
|
23
|
+
entropy_read(uint8_t * buf, size_t buflen)
|
24
|
+
{
|
25
|
+
int fd;
|
26
|
+
ssize_t lenread;
|
27
|
+
|
28
|
+
/* Sanity-check the buffer size. */
|
29
|
+
if (buflen > SSIZE_MAX) {
|
30
|
+
warn0("Programmer error: "
|
31
|
+
"Trying to read insane amount of random data: %zu",
|
32
|
+
buflen);
|
33
|
+
goto err0;
|
34
|
+
}
|
35
|
+
|
36
|
+
/* Open /dev/urandom. */
|
37
|
+
if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
|
38
|
+
warnp("open(/dev/urandom)");
|
39
|
+
goto err0;
|
40
|
+
}
|
41
|
+
|
42
|
+
/* Read bytes until we have filled the buffer. */
|
43
|
+
while (buflen > 0) {
|
44
|
+
if ((lenread = read(fd, buf, buflen)) == -1) {
|
45
|
+
warnp("read(/dev/urandom)");
|
46
|
+
goto err1;
|
47
|
+
}
|
48
|
+
|
49
|
+
/* The random device should never EOF. */
|
50
|
+
if (lenread == 0) {
|
51
|
+
warn0("EOF on /dev/urandom?");
|
52
|
+
goto err1;
|
53
|
+
}
|
54
|
+
|
55
|
+
/* We've filled a portion of the buffer. */
|
56
|
+
buf += lenread;
|
57
|
+
buflen -= lenread;
|
58
|
+
}
|
59
|
+
|
60
|
+
/* Close the device. */
|
61
|
+
while (close(fd) == -1) {
|
62
|
+
if (errno != EINTR) {
|
63
|
+
warnp("close(/dev/urandom)");
|
64
|
+
goto err0;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
/* Success! */
|
69
|
+
return (0);
|
70
|
+
|
71
|
+
err1:
|
72
|
+
close(fd);
|
73
|
+
err0:
|
74
|
+
/* Failure! */
|
75
|
+
return (-1);
|
76
|
+
}
|