spiped 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,98 @@
|
|
|
1
|
+
# Program name.
|
|
2
|
+
PROG = spiped
|
|
3
|
+
MAN1 = ${PROG}.1
|
|
4
|
+
|
|
5
|
+
# Libraries which are sometimes merged into libc
|
|
6
|
+
LDADD = -lrt
|
|
7
|
+
#LDADD += -lxnet # Missing on FreeBSD
|
|
8
|
+
|
|
9
|
+
# Library code required
|
|
10
|
+
LDADD_REQ = -lcrypto
|
|
11
|
+
LDADD_REQ += -lpthread
|
|
12
|
+
|
|
13
|
+
# spiped code
|
|
14
|
+
SRCS = main.c
|
|
15
|
+
SRCS += dispatch.c
|
|
16
|
+
|
|
17
|
+
# spipe protocol
|
|
18
|
+
.PATH.c : ../proto
|
|
19
|
+
SRCS += proto_conn.c
|
|
20
|
+
SRCS += proto_crypt.c
|
|
21
|
+
SRCS += proto_handshake.c
|
|
22
|
+
SRCS += proto_pipe.c
|
|
23
|
+
IDIRS += -I ../proto
|
|
24
|
+
|
|
25
|
+
# Fundamental algorithms
|
|
26
|
+
.PATH.c : ../libcperciva/alg
|
|
27
|
+
SRCS += sha256.c
|
|
28
|
+
IDIRS += -I ../libcperciva/alg
|
|
29
|
+
|
|
30
|
+
# Data structures
|
|
31
|
+
.PATH.c : ../libcperciva/datastruct
|
|
32
|
+
SRCS += elasticarray.c
|
|
33
|
+
SRCS += ptrheap.c
|
|
34
|
+
SRCS += timerqueue.c
|
|
35
|
+
IDIRS += -I ../libcperciva/datastruct
|
|
36
|
+
|
|
37
|
+
# DNS resolution
|
|
38
|
+
.PATH.c : ../lib/dnsthread
|
|
39
|
+
SRCS += dnsthread.c
|
|
40
|
+
IDIRS += -I ../lib/dnsthread
|
|
41
|
+
|
|
42
|
+
# Utility functions
|
|
43
|
+
.PATH.c : ../libcperciva/util
|
|
44
|
+
SRCS += asprintf.c
|
|
45
|
+
SRCS += daemonize.c
|
|
46
|
+
SRCS += entropy.c
|
|
47
|
+
SRCS += insecure_memzero.c
|
|
48
|
+
SRCS += monoclock.c
|
|
49
|
+
SRCS += noeintr.c
|
|
50
|
+
SRCS += sock.c
|
|
51
|
+
SRCS += sock_util.c
|
|
52
|
+
SRCS += warnp.c
|
|
53
|
+
IDIRS += -I ../libcperciva/util
|
|
54
|
+
|
|
55
|
+
# CPU features detection
|
|
56
|
+
.PATH.c : ../libcperciva/cpusupport
|
|
57
|
+
SRCS += cpusupport_x86_aesni.c
|
|
58
|
+
IDIRS += -I ../libcperciva/cpusupport
|
|
59
|
+
|
|
60
|
+
# Event loop
|
|
61
|
+
.PATH.c : ../libcperciva/events
|
|
62
|
+
SRCS += events_immediate.c
|
|
63
|
+
SRCS += events_network.c
|
|
64
|
+
SRCS += events_network_selectstats.c
|
|
65
|
+
SRCS += events_timer.c
|
|
66
|
+
SRCS += events.c
|
|
67
|
+
IDIRS += -I ../libcperciva/events
|
|
68
|
+
|
|
69
|
+
# Event-driven networking
|
|
70
|
+
.PATH.c : ../libcperciva/network
|
|
71
|
+
SRCS += network_accept.c
|
|
72
|
+
SRCS += network_connect.c
|
|
73
|
+
SRCS += network_read.c
|
|
74
|
+
SRCS += network_write.c
|
|
75
|
+
IDIRS += -I ../libcperciva/network
|
|
76
|
+
|
|
77
|
+
# Crypto code
|
|
78
|
+
.PATH.c : ../libcperciva/crypto
|
|
79
|
+
SRCS += crypto_aes.c
|
|
80
|
+
SRCS += crypto_aes_aesni.c
|
|
81
|
+
SRCS += crypto_aesctr.c
|
|
82
|
+
SRCS += crypto_dh.c
|
|
83
|
+
SRCS += crypto_dh_group14.c
|
|
84
|
+
SRCS += crypto_entropy.c
|
|
85
|
+
SRCS += crypto_verify_bytes.c
|
|
86
|
+
IDIRS += -I ../libcperciva/crypto
|
|
87
|
+
|
|
88
|
+
crypto_aes_aesni.o: crypto_aes_aesni.c cpusupport-config.h
|
|
89
|
+
. ./cpusupport-config.h; ${CC} ${CFLAGS} $${CFLAGS_X86_AESNI} -c $< -o $@
|
|
90
|
+
cflags-crypto_aes_aesni.o=$${CFLAGS_X86_AESNI}
|
|
91
|
+
|
|
92
|
+
# Debugging options
|
|
93
|
+
CFLAGS += -g
|
|
94
|
+
#CFLAGS += -DNDEBUG
|
|
95
|
+
#CFLAGS += -DDEBUG
|
|
96
|
+
#CFLAGS += -pg
|
|
97
|
+
|
|
98
|
+
.include <bsd.prog.mk>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
spiped usage
|
|
2
|
+
============
|
|
3
|
+
|
|
4
|
+
usage: spiped {-e | -d} -s <source socket> -t <target socket> -k <key file>
|
|
5
|
+
[-DFj] [-f | -g] [-n <max # connections>] [-o <connection timeout>]
|
|
6
|
+
[-p <pidfile>] [-r <rtime> | -R]
|
|
7
|
+
|
|
8
|
+
Options:
|
|
9
|
+
-e
|
|
10
|
+
Take unencrypted connections from the source socket and send
|
|
11
|
+
encrypted connections to the target socket.
|
|
12
|
+
-d
|
|
13
|
+
Take encrypted connections from the source socket and send
|
|
14
|
+
unencrypted connections to the target socket.
|
|
15
|
+
-s <source socket>
|
|
16
|
+
Address on which spiped should listen for incoming connections.
|
|
17
|
+
Must be in one of the following formats:
|
|
18
|
+
/absolute/path/to/unix/socket
|
|
19
|
+
host.name:port
|
|
20
|
+
[ip.v4.ad.dr]:port
|
|
21
|
+
[ipv6::addr]:port
|
|
22
|
+
Note that hostnames are resolved when spiped is launched and are not
|
|
23
|
+
re-resolved later; thus if DNS entries change spiped will continue to
|
|
24
|
+
connect to the expired address.
|
|
25
|
+
-t <target socket>
|
|
26
|
+
Address to which spiped should connect.
|
|
27
|
+
-k <key file>
|
|
28
|
+
Use the provided key file to authenticate and encrypt.
|
|
29
|
+
-D
|
|
30
|
+
Wait for DNS. Normally when spiped is launched it resolves addresses
|
|
31
|
+
and binds to its source socket before the parent process returns; with
|
|
32
|
+
this option it will daemonize first and retry failed DNS lookups until
|
|
33
|
+
they succeed. This allows spiped to launch even if DNS isn't set up
|
|
34
|
+
yet, but at the expense of losing the guarantee that once spiped has
|
|
35
|
+
finished launching it will be ready to create pipes.
|
|
36
|
+
-f
|
|
37
|
+
Use fast/weak handshaking: This reduces the CPU time spent in the
|
|
38
|
+
initial connection setup, at the expense of losing perfect forward
|
|
39
|
+
secrecy.
|
|
40
|
+
-g
|
|
41
|
+
Require perfect forward secrecy by dropping connections if the other
|
|
42
|
+
host is using the -f option.
|
|
43
|
+
-F
|
|
44
|
+
Run in foreground. This can be useful with systems like daemontools.
|
|
45
|
+
-j
|
|
46
|
+
Disable transport layer keep-alives. (By default they are enabled.)
|
|
47
|
+
-n <max # connections>
|
|
48
|
+
Limit on the number of simultaneous connections allowed. Defaults
|
|
49
|
+
to 100 connections.
|
|
50
|
+
-o <connection timeout>
|
|
51
|
+
Timeout, in seconds, after which an attempt to connect to the target
|
|
52
|
+
or a protocol handshake will be aborted (and the connection dropped)
|
|
53
|
+
if not completed. Defaults to 5s.
|
|
54
|
+
-p <pidfile>
|
|
55
|
+
File to which spiped's process ID should be written. Defaults to
|
|
56
|
+
<source socket>.pid (in the current directory if <source socket> is
|
|
57
|
+
not an absolute path).
|
|
58
|
+
-r <rtime>
|
|
59
|
+
Re-resolve the address of <target socket> every <rtime> seconds.
|
|
60
|
+
Defaults to re-resolution every 60 seconds.
|
|
61
|
+
-R
|
|
62
|
+
Do not re-resolve the address of <target socket>.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#include <stdint.h>
|
|
2
|
+
#include <stdlib.h>
|
|
3
|
+
#include <string.h>
|
|
4
|
+
|
|
5
|
+
#include "dnsthread.h"
|
|
6
|
+
#include "events.h"
|
|
7
|
+
#include "network.h"
|
|
8
|
+
#include "sock.h"
|
|
9
|
+
#include "sock_util.h"
|
|
10
|
+
#include "warnp.h"
|
|
11
|
+
|
|
12
|
+
#include "proto_conn.h"
|
|
13
|
+
|
|
14
|
+
#include "dispatch.h"
|
|
15
|
+
|
|
16
|
+
struct accept_state {
|
|
17
|
+
int s;
|
|
18
|
+
const char * tgt;
|
|
19
|
+
struct sock_addr ** sas;
|
|
20
|
+
double rtime;
|
|
21
|
+
int decr;
|
|
22
|
+
int nofps;
|
|
23
|
+
int requirefps;
|
|
24
|
+
int nokeepalive;
|
|
25
|
+
const struct proto_secret * K;
|
|
26
|
+
size_t nconn;
|
|
27
|
+
size_t nconn_max;
|
|
28
|
+
double timeo;
|
|
29
|
+
void * accept_cookie;
|
|
30
|
+
DNSTHREAD T;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
static int callback_gotconn(void *, int);
|
|
34
|
+
static int callback_resolveagain(void *);
|
|
35
|
+
|
|
36
|
+
/* Callback from address resolution. */
|
|
37
|
+
static int
|
|
38
|
+
callback_resolve(void * cookie, struct sock_addr ** sas)
|
|
39
|
+
{
|
|
40
|
+
struct accept_state * A = cookie;
|
|
41
|
+
|
|
42
|
+
/* If the address resolution succeeded... */
|
|
43
|
+
if (sas != NULL) {
|
|
44
|
+
/* Free the old addresses. */
|
|
45
|
+
sock_addr_freelist(A->sas);
|
|
46
|
+
|
|
47
|
+
/* Use the new addresses. */
|
|
48
|
+
A->sas = sas;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* Wait a while before resolving again. */
|
|
52
|
+
if (events_timer_register_double(callback_resolveagain,
|
|
53
|
+
A, A->rtime) == NULL)
|
|
54
|
+
goto err0;
|
|
55
|
+
|
|
56
|
+
/* Success! */
|
|
57
|
+
return (0);
|
|
58
|
+
|
|
59
|
+
err0:
|
|
60
|
+
/* Failure! */
|
|
61
|
+
return (-1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Timer callback to trigger another address resolution. */
|
|
65
|
+
static int
|
|
66
|
+
callback_resolveagain(void * cookie)
|
|
67
|
+
{
|
|
68
|
+
struct accept_state * A = cookie;
|
|
69
|
+
|
|
70
|
+
/* Re-resolve the target address. */
|
|
71
|
+
return (dnsthread_resolveone(A->T, A->tgt, callback_resolve, A));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Non-blocking accept, if we can have more connections. */
|
|
75
|
+
static int
|
|
76
|
+
doaccept(struct accept_state * A)
|
|
77
|
+
{
|
|
78
|
+
int rc = 0;
|
|
79
|
+
|
|
80
|
+
/* If we can, accept a new connection. */
|
|
81
|
+
if ((A->nconn < A->nconn_max) && (A->accept_cookie == NULL)) {
|
|
82
|
+
if ((A->accept_cookie =
|
|
83
|
+
network_accept(A->s, callback_gotconn, A)) == NULL)
|
|
84
|
+
rc = -1;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Return success/fail status. */
|
|
88
|
+
return (rc);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* A connection has closed. Accept more if necessary. */
|
|
92
|
+
static int
|
|
93
|
+
callback_conndied(void * cookie)
|
|
94
|
+
{
|
|
95
|
+
struct accept_state * A = cookie;
|
|
96
|
+
|
|
97
|
+
/* We've lost a connection. */
|
|
98
|
+
A->nconn -= 1;
|
|
99
|
+
|
|
100
|
+
/* Maybe accept more connections. */
|
|
101
|
+
return (doaccept(A));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Handle an incoming connection. */
|
|
105
|
+
static int
|
|
106
|
+
callback_gotconn(void * cookie, int s)
|
|
107
|
+
{
|
|
108
|
+
struct accept_state * A = cookie;
|
|
109
|
+
struct sock_addr ** sas;
|
|
110
|
+
|
|
111
|
+
/* This accept is no longer in progress. */
|
|
112
|
+
A->accept_cookie = NULL;
|
|
113
|
+
|
|
114
|
+
/* If we got a -1 descriptor, something went seriously wrong. */
|
|
115
|
+
if (s == -1) {
|
|
116
|
+
warnp("network_accept failed");
|
|
117
|
+
goto err0;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* We have gained a connection. */
|
|
121
|
+
A->nconn += 1;
|
|
122
|
+
|
|
123
|
+
/* Duplicate the target address list. */
|
|
124
|
+
if ((sas = sock_addr_duplist(A->sas)) == NULL)
|
|
125
|
+
goto err1;
|
|
126
|
+
|
|
127
|
+
/* Create a new connection. */
|
|
128
|
+
if (proto_conn_create(s, sas, A->decr, A->nofps, A->requirefps,
|
|
129
|
+
A->nokeepalive, A->K, A->timeo, callback_conndied, A)) {
|
|
130
|
+
warnp("Failure setting up new connection");
|
|
131
|
+
goto err2;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Accept another connection if we can. */
|
|
135
|
+
if (doaccept(A))
|
|
136
|
+
goto err0;
|
|
137
|
+
|
|
138
|
+
/* Success! */
|
|
139
|
+
return (0);
|
|
140
|
+
|
|
141
|
+
err2:
|
|
142
|
+
sock_addr_freelist(sas);
|
|
143
|
+
err1:
|
|
144
|
+
A->nconn -= 1;
|
|
145
|
+
close(s);
|
|
146
|
+
err0:
|
|
147
|
+
/* Failure! */
|
|
148
|
+
return (-1);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* dispatch_accept(s, tgt, rtime, sas, decr, nofps, requirefps, nokeepalive, K,
|
|
153
|
+
* nconn_max, timeo):
|
|
154
|
+
* Start accepting connections on the socket ${s}. Connect to the target
|
|
155
|
+
* ${tgt}, re-resolving it every ${rtime} seconds if ${rtime} > 0; on address
|
|
156
|
+
* resolution failure use the most recent successfully obtained addresses, or
|
|
157
|
+
* the addresses ${sas}. If ${decr} is 0, encrypt the outgoing connections; if
|
|
158
|
+
* ${decr} is non-zero, decrypt the incoming connections. Don't accept more
|
|
159
|
+
* than ${nconn_max} connections. If ${nofps} is non-zero, don't use perfect
|
|
160
|
+
* forward secrecy. If {$requirefps} is non-zero, require that both ends use
|
|
161
|
+
* perfect forward secrecy. Enable transport layer keep-alives (if applicable)
|
|
162
|
+
* if and only if ${nokeepalive} is zero. Drop connections if the handshake or
|
|
163
|
+
* connecting to the target takes more than ${timeo} seconds.
|
|
164
|
+
*/
|
|
165
|
+
int
|
|
166
|
+
dispatch_accept(int s, const char * tgt, double rtime, struct sock_addr ** sas,
|
|
167
|
+
int decr, int nofps, int requirefps, int nokeepalive,
|
|
168
|
+
const struct proto_secret * K, size_t nconn_max, double timeo)
|
|
169
|
+
{
|
|
170
|
+
struct accept_state * A;
|
|
171
|
+
|
|
172
|
+
/* Bake a cookie. */
|
|
173
|
+
if ((A = malloc(sizeof(struct accept_state))) == NULL)
|
|
174
|
+
goto err0;
|
|
175
|
+
A->s = s;
|
|
176
|
+
A->tgt = tgt;
|
|
177
|
+
A->sas = sas;
|
|
178
|
+
A->rtime = rtime;
|
|
179
|
+
A->decr = decr;
|
|
180
|
+
A->nofps = nofps;
|
|
181
|
+
A->requirefps = requirefps;
|
|
182
|
+
A->nokeepalive = nokeepalive;
|
|
183
|
+
A->K = K;
|
|
184
|
+
A->nconn = 0;
|
|
185
|
+
A->nconn_max = nconn_max;
|
|
186
|
+
A->timeo = timeo;
|
|
187
|
+
A->accept_cookie = NULL;
|
|
188
|
+
|
|
189
|
+
/* If address re-resolution is enabled... */
|
|
190
|
+
if (rtime > 0.0) {
|
|
191
|
+
/* Launch an address resolution thread. */
|
|
192
|
+
A->T = dnsthread_spawn();
|
|
193
|
+
|
|
194
|
+
/* Re-resolve the target address after a while. */
|
|
195
|
+
if (events_timer_register_double(callback_resolveagain,
|
|
196
|
+
A, A->rtime) == NULL)
|
|
197
|
+
goto err1;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* Accept a connection. */
|
|
201
|
+
if (doaccept(A))
|
|
202
|
+
goto err1;
|
|
203
|
+
|
|
204
|
+
/* Success! */
|
|
205
|
+
return (0);
|
|
206
|
+
|
|
207
|
+
err1:
|
|
208
|
+
if (rtime > 0.0)
|
|
209
|
+
dnsthread_kill(A->T);
|
|
210
|
+
free(A);
|
|
211
|
+
err0:
|
|
212
|
+
/* Failure! */
|
|
213
|
+
return (-1);
|
|
214
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#ifndef _DISPATCH_H_
|
|
2
|
+
#define _DISPATCH_H_
|
|
3
|
+
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
|
|
6
|
+
/* Opaque structures. */
|
|
7
|
+
struct proto_secret;
|
|
8
|
+
struct sock_addr;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* dispatch_accept(s, tgt, rtime, sas, decr, nofps, requirefps, nokeepalive, K,
|
|
12
|
+
* nconn_max, timeo):
|
|
13
|
+
* Start accepting connections on the socket ${s}. Connect to the target
|
|
14
|
+
* ${tgt}, re-resolving it every ${rtime} seconds if ${rtime} > 0; on address
|
|
15
|
+
* resolution failure use the most recent successfully obtained addresses, or
|
|
16
|
+
* the addresses ${sas}. If ${decr} is 0, encrypt the outgoing connections; if
|
|
17
|
+
* ${decr} is non-zero, decrypt the incoming connections. Don't accept more
|
|
18
|
+
* than ${nconn_max} connections. If ${nofps} is non-zero, don't use perfect
|
|
19
|
+
* forward secrecy. If {$requirefps} is non-zero, require that both ends use
|
|
20
|
+
* perfect forward secrecy. Enable transport layer keep-alives (if applicable)
|
|
21
|
+
* if and only if ${nokeepalive} is zero. Drop connections if the handshake or
|
|
22
|
+
* connecting to the target takes more than ${timeo} seconds.
|
|
23
|
+
*/
|
|
24
|
+
int dispatch_accept(int, const char *, double, struct sock_addr **, int, int,
|
|
25
|
+
int, int, const struct proto_secret *, size_t, double);
|
|
26
|
+
|
|
27
|
+
#endif /* !_DISPATCH_H_ */
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
#include <inttypes.h>
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
#include <stdlib.h>
|
|
4
|
+
#include <string.h>
|
|
5
|
+
#include <unistd.h>
|
|
6
|
+
|
|
7
|
+
#include "asprintf.h"
|
|
8
|
+
#include "daemonize.h"
|
|
9
|
+
#include "events.h"
|
|
10
|
+
#include "sock.h"
|
|
11
|
+
#include "warnp.h"
|
|
12
|
+
|
|
13
|
+
#include "dispatch.h"
|
|
14
|
+
#include "proto_crypt.h"
|
|
15
|
+
|
|
16
|
+
static void
|
|
17
|
+
usage(void)
|
|
18
|
+
{
|
|
19
|
+
|
|
20
|
+
fprintf(stderr, "usage: spiped {-e | -d} -s <source socket> "
|
|
21
|
+
"-t <target socket> -k <key file>\n"
|
|
22
|
+
" [-DFj] [-f | -g] [-n <max # connections>] "
|
|
23
|
+
"[-o <connection timeout>]\n"
|
|
24
|
+
" [-p <pidfile>] [-r <rtime> | -R]\n");
|
|
25
|
+
exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Simplify error-handling in command-line parse loop. */
|
|
29
|
+
#define OPT_EPARSE(opt, arg) do { \
|
|
30
|
+
warnp("Error parsing argument: -%c %s", opt, arg); \
|
|
31
|
+
exit(1); \
|
|
32
|
+
} while (0)
|
|
33
|
+
|
|
34
|
+
int
|
|
35
|
+
main(int argc, char * argv[])
|
|
36
|
+
{
|
|
37
|
+
/* Command-line parameters. */
|
|
38
|
+
int opt_d = 0;
|
|
39
|
+
int opt_D = 0;
|
|
40
|
+
int opt_e = 0;
|
|
41
|
+
int opt_f = 0;
|
|
42
|
+
int opt_g = 0;
|
|
43
|
+
int opt_F = 0;
|
|
44
|
+
int opt_j = 0;
|
|
45
|
+
const char * opt_k = NULL;
|
|
46
|
+
intmax_t opt_n = 0;
|
|
47
|
+
double opt_o = 0.0;
|
|
48
|
+
char * opt_p = NULL;
|
|
49
|
+
double opt_r = 0.0;
|
|
50
|
+
int opt_R = 0;
|
|
51
|
+
const char * opt_s = NULL;
|
|
52
|
+
const char * opt_t = NULL;
|
|
53
|
+
|
|
54
|
+
/* Working variables. */
|
|
55
|
+
struct sock_addr ** sas_s;
|
|
56
|
+
struct sock_addr ** sas_t;
|
|
57
|
+
struct proto_secret * K;
|
|
58
|
+
int ch;
|
|
59
|
+
int s;
|
|
60
|
+
|
|
61
|
+
WARNP_INIT;
|
|
62
|
+
|
|
63
|
+
/* Parse the command line. */
|
|
64
|
+
while ((ch = getopt(argc, argv, "dDefFgjk:n:o:r:Rp:s:t:")) != -1) {
|
|
65
|
+
switch (ch) {
|
|
66
|
+
case 'd':
|
|
67
|
+
if (opt_d || opt_e)
|
|
68
|
+
usage();
|
|
69
|
+
opt_d = 1;
|
|
70
|
+
break;
|
|
71
|
+
case 'D':
|
|
72
|
+
if (opt_D)
|
|
73
|
+
usage();
|
|
74
|
+
opt_D = 1;
|
|
75
|
+
break;
|
|
76
|
+
case 'e':
|
|
77
|
+
if (opt_d || opt_e)
|
|
78
|
+
usage();
|
|
79
|
+
opt_e = 1;
|
|
80
|
+
break;
|
|
81
|
+
case 'f':
|
|
82
|
+
if (opt_f)
|
|
83
|
+
usage();
|
|
84
|
+
opt_f = 1;
|
|
85
|
+
break;
|
|
86
|
+
case 'F':
|
|
87
|
+
if (opt_F)
|
|
88
|
+
usage();
|
|
89
|
+
opt_F = 1;
|
|
90
|
+
break;
|
|
91
|
+
case 'g':
|
|
92
|
+
if (opt_g)
|
|
93
|
+
usage();
|
|
94
|
+
opt_g = 1;
|
|
95
|
+
break;
|
|
96
|
+
case 'j':
|
|
97
|
+
if (opt_j)
|
|
98
|
+
usage();
|
|
99
|
+
opt_j = 1;
|
|
100
|
+
break;
|
|
101
|
+
case 'k':
|
|
102
|
+
if (opt_k)
|
|
103
|
+
usage();
|
|
104
|
+
opt_k = optarg;
|
|
105
|
+
break;
|
|
106
|
+
case 'n':
|
|
107
|
+
if (opt_n != 0)
|
|
108
|
+
usage();
|
|
109
|
+
if ((opt_n = strtoimax(optarg, NULL, 0)) == 0) {
|
|
110
|
+
warn0("Invalid option: -n %s", optarg);
|
|
111
|
+
exit(1);
|
|
112
|
+
}
|
|
113
|
+
if ((opt_n <= 0) || (opt_n > 500)) {
|
|
114
|
+
warn0("The parameter to -n must be between 1 and 500\n");
|
|
115
|
+
exit(1);
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
case 'o':
|
|
119
|
+
if (opt_o != 0.0)
|
|
120
|
+
usage();
|
|
121
|
+
if ((opt_o = strtod(optarg, NULL)) == 0.0) {
|
|
122
|
+
warn0("Invalid option: -o %s", optarg);
|
|
123
|
+
exit(1);
|
|
124
|
+
}
|
|
125
|
+
break;
|
|
126
|
+
case 'p':
|
|
127
|
+
if (opt_p)
|
|
128
|
+
usage();
|
|
129
|
+
if ((opt_p = strdup(optarg)) == NULL)
|
|
130
|
+
OPT_EPARSE(ch, optarg);
|
|
131
|
+
break;
|
|
132
|
+
case 'r':
|
|
133
|
+
if (opt_r != 0.0)
|
|
134
|
+
usage();
|
|
135
|
+
if ((opt_r = strtod(optarg, NULL)) == 0.0) {
|
|
136
|
+
warn0("Invalid option: -r %s", optarg);
|
|
137
|
+
exit(1);
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
case 'R':
|
|
141
|
+
if (opt_R)
|
|
142
|
+
usage();
|
|
143
|
+
opt_R = 1;
|
|
144
|
+
break;
|
|
145
|
+
case 's':
|
|
146
|
+
if (opt_s)
|
|
147
|
+
usage();
|
|
148
|
+
opt_s = optarg;
|
|
149
|
+
break;
|
|
150
|
+
case 't':
|
|
151
|
+
if (opt_t)
|
|
152
|
+
usage();
|
|
153
|
+
opt_t = optarg;
|
|
154
|
+
break;
|
|
155
|
+
default:
|
|
156
|
+
usage();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* We should have processed all the arguments. */
|
|
161
|
+
if (argc != optind)
|
|
162
|
+
usage();
|
|
163
|
+
|
|
164
|
+
/* Set defaults. */
|
|
165
|
+
if (opt_n == 0)
|
|
166
|
+
opt_n = 100;
|
|
167
|
+
if (opt_o == 0.0)
|
|
168
|
+
opt_o = 5.0;
|
|
169
|
+
if (opt_r == 0.0)
|
|
170
|
+
opt_r = 60.0;
|
|
171
|
+
|
|
172
|
+
/* Sanity-check options. */
|
|
173
|
+
if (!opt_d && !opt_e)
|
|
174
|
+
usage();
|
|
175
|
+
if (opt_f && opt_g)
|
|
176
|
+
usage();
|
|
177
|
+
if (opt_k == NULL)
|
|
178
|
+
usage();
|
|
179
|
+
if (!(opt_o > 0.0))
|
|
180
|
+
usage();
|
|
181
|
+
if ((opt_r != 60.0) && opt_R)
|
|
182
|
+
usage();
|
|
183
|
+
if (opt_s == NULL)
|
|
184
|
+
usage();
|
|
185
|
+
if (opt_t == NULL)
|
|
186
|
+
usage();
|
|
187
|
+
|
|
188
|
+
/* Figure out where our pid should be written. */
|
|
189
|
+
if (opt_p == NULL) {
|
|
190
|
+
if (asprintf(&opt_p, "%s.pid", opt_s) == -1) {
|
|
191
|
+
warnp("asprintf");
|
|
192
|
+
exit(1);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* Daemonize early if we're going to wait for DNS to be ready. */
|
|
197
|
+
if (opt_D && !opt_F && daemonize(opt_p)) {
|
|
198
|
+
warnp("Failed to daemonize");
|
|
199
|
+
exit(1);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Resolve source address. */
|
|
203
|
+
while ((sas_s = sock_resolve(opt_s)) == NULL) {
|
|
204
|
+
if (!opt_D) {
|
|
205
|
+
warnp("Error resolving socket address: %s", opt_s);
|
|
206
|
+
exit(1);
|
|
207
|
+
}
|
|
208
|
+
sleep(1);
|
|
209
|
+
}
|
|
210
|
+
if (sas_s[0] == NULL) {
|
|
211
|
+
warn0("No addresses found for %s", opt_s);
|
|
212
|
+
exit(1);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* Resolve target address. */
|
|
216
|
+
while ((sas_t = sock_resolve(opt_t)) == NULL) {
|
|
217
|
+
if (!opt_D) {
|
|
218
|
+
warnp("Error resolving socket address: %s", opt_t);
|
|
219
|
+
exit(1);
|
|
220
|
+
}
|
|
221
|
+
sleep(1);
|
|
222
|
+
}
|
|
223
|
+
if (sas_t[0] == NULL) {
|
|
224
|
+
warn0("No addresses found for %s", opt_t);
|
|
225
|
+
exit(1);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/* Load the keying data. */
|
|
229
|
+
if ((K = proto_crypt_secret(opt_k)) == NULL) {
|
|
230
|
+
warnp("Error reading shared secret");
|
|
231
|
+
exit(1);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* Create and bind a socket, and mark it as listening. */
|
|
235
|
+
if (sas_s[1] != NULL)
|
|
236
|
+
warn0("Listening on first of multiple addresses found for %s",
|
|
237
|
+
opt_s);
|
|
238
|
+
if ((s = sock_listener(sas_s[0])) == -1)
|
|
239
|
+
exit(1);
|
|
240
|
+
|
|
241
|
+
/* Daemonize and write pid. */
|
|
242
|
+
if (!opt_F && daemonize(opt_p)) {
|
|
243
|
+
warnp("Failed to daemonize");
|
|
244
|
+
exit(1);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/* Start accepting connections. */
|
|
248
|
+
if (dispatch_accept(s, opt_t, opt_R ? 0.0 : opt_r, sas_t, opt_d,
|
|
249
|
+
opt_f, opt_g, opt_j, K, opt_n, opt_o)) {
|
|
250
|
+
warnp("Failed to initialize connection acceptor");
|
|
251
|
+
exit(1);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* Infinite loop handling events. */
|
|
255
|
+
do {
|
|
256
|
+
if (events_run()) {
|
|
257
|
+
warnp("Error running event loop");
|
|
258
|
+
exit(1);
|
|
259
|
+
}
|
|
260
|
+
} while (1);
|
|
261
|
+
|
|
262
|
+
/* NOTREACHED */
|
|
263
|
+
/*
|
|
264
|
+
* If we could reach this point, we would free memory, close sockets,
|
|
265
|
+
* and otherwise clean up here.
|
|
266
|
+
*/
|
|
267
|
+
}
|