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,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
|
+
}
|