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,330 @@
|
|
|
1
|
+
#include <assert.h>
|
|
2
|
+
#include <stdint.h>
|
|
3
|
+
#include <stdlib.h>
|
|
4
|
+
#include <string.h>
|
|
5
|
+
|
|
6
|
+
#include "crypto_entropy.h"
|
|
7
|
+
#include "network.h"
|
|
8
|
+
|
|
9
|
+
#include "proto_crypt.h"
|
|
10
|
+
|
|
11
|
+
#include "proto_handshake.h"
|
|
12
|
+
|
|
13
|
+
struct handshake_cookie {
|
|
14
|
+
int (* callback)(void *, struct proto_keys *, struct proto_keys *);
|
|
15
|
+
void * cookie;
|
|
16
|
+
int s;
|
|
17
|
+
int decr;
|
|
18
|
+
int nofps;
|
|
19
|
+
int requirefps;
|
|
20
|
+
const struct proto_secret * K;
|
|
21
|
+
uint8_t nonce_local[PCRYPT_NONCE_LEN];
|
|
22
|
+
uint8_t nonce_remote[PCRYPT_NONCE_LEN];
|
|
23
|
+
uint8_t dhmac_local[PCRYPT_DHMAC_LEN];
|
|
24
|
+
uint8_t dhmac_remote[PCRYPT_DHMAC_LEN];
|
|
25
|
+
uint8_t x[PCRYPT_X_LEN];
|
|
26
|
+
uint8_t yh_local[PCRYPT_YH_LEN];
|
|
27
|
+
uint8_t yh_remote[PCRYPT_YH_LEN];
|
|
28
|
+
void * read_cookie;
|
|
29
|
+
void * write_cookie;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
static int callback_nonce_write(void *, ssize_t);
|
|
33
|
+
static int callback_nonce_read(void *, ssize_t);
|
|
34
|
+
static int gotnonces(struct handshake_cookie *);
|
|
35
|
+
static int dhread(struct handshake_cookie *);
|
|
36
|
+
static int callback_dh_read(void *, ssize_t);
|
|
37
|
+
static int dhwrite(struct handshake_cookie *);
|
|
38
|
+
static int callback_dh_write(void *, ssize_t);
|
|
39
|
+
static int handshakedone(struct handshake_cookie *);
|
|
40
|
+
|
|
41
|
+
/* The handshake failed. Call back and clean up. */
|
|
42
|
+
static int
|
|
43
|
+
handshakefail(struct handshake_cookie * H)
|
|
44
|
+
{
|
|
45
|
+
int rc;
|
|
46
|
+
|
|
47
|
+
/* Cancel any pending network read or write. */
|
|
48
|
+
if (H->read_cookie != NULL)
|
|
49
|
+
network_read_cancel(H->read_cookie);
|
|
50
|
+
if (H->write_cookie != NULL)
|
|
51
|
+
network_write_cancel(H->write_cookie);
|
|
52
|
+
|
|
53
|
+
/* Perform the callback. */
|
|
54
|
+
rc = (H->callback)(H->cookie, NULL, NULL);
|
|
55
|
+
|
|
56
|
+
/* Free the cookie. */
|
|
57
|
+
free(H);
|
|
58
|
+
|
|
59
|
+
/* Return status from callback. */
|
|
60
|
+
return (rc);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* proto_handshake(s, decr, nofps, requirefps, K, callback, cookie):
|
|
65
|
+
* Perform a protocol handshake on socket ${s}. If ${decr} is non-zero we are
|
|
66
|
+
* at the receiving end of the connection; otherwise at the sending end. If
|
|
67
|
+
* ${nofps} is non-zero, perform a "weak" handshake without forward perfect
|
|
68
|
+
* secrecy. If ${requirefps} is non-zero, drop the connection if the other
|
|
69
|
+
* end attempts to perform a "weak" handshake. The shared protocol secret is
|
|
70
|
+
* ${K}. Upon completion, invoke ${callback}(${cookie}, f, r), where f
|
|
71
|
+
* contains the keys needed for the forward direction and r contains the keys
|
|
72
|
+
* needed for the reverse direction; or f = r = NULL if the handshake failed.
|
|
73
|
+
* Return a cookie which can be passed to proto_handshake_cancel to cancel the
|
|
74
|
+
* handshake.
|
|
75
|
+
|
|
76
|
+
*/
|
|
77
|
+
void *
|
|
78
|
+
proto_handshake(int s, int decr, int nofps, int requirefps,
|
|
79
|
+
const struct proto_secret * K,
|
|
80
|
+
int (* callback)(void *, struct proto_keys *, struct proto_keys *),
|
|
81
|
+
void * cookie)
|
|
82
|
+
{
|
|
83
|
+
struct handshake_cookie * H;
|
|
84
|
+
|
|
85
|
+
/* Bake a cookie. */
|
|
86
|
+
if ((H = malloc(sizeof(struct handshake_cookie))) == NULL)
|
|
87
|
+
goto err0;
|
|
88
|
+
H->callback = callback;
|
|
89
|
+
H->cookie = cookie;
|
|
90
|
+
H->s = s;
|
|
91
|
+
H->decr = decr;
|
|
92
|
+
H->nofps = nofps;
|
|
93
|
+
H->requirefps = requirefps;
|
|
94
|
+
H->K = K;
|
|
95
|
+
|
|
96
|
+
/* Generate a 32-byte connection nonce. */
|
|
97
|
+
if (crypto_entropy_read(H->nonce_local, 32))
|
|
98
|
+
goto err1;
|
|
99
|
+
|
|
100
|
+
/* Send our nonce. */
|
|
101
|
+
if ((H->write_cookie = network_write(s, H->nonce_local, 32, 32,
|
|
102
|
+
callback_nonce_write, H)) == NULL)
|
|
103
|
+
goto err1;
|
|
104
|
+
|
|
105
|
+
/* Read the other party's nonce. */
|
|
106
|
+
if ((H->read_cookie = network_read(s, H->nonce_remote, 32, 32,
|
|
107
|
+
callback_nonce_read, H)) == NULL)
|
|
108
|
+
goto err2;
|
|
109
|
+
|
|
110
|
+
/* Success! */
|
|
111
|
+
return (H);
|
|
112
|
+
|
|
113
|
+
err2:
|
|
114
|
+
network_write_cancel(H->write_cookie);
|
|
115
|
+
err1:
|
|
116
|
+
free(H);
|
|
117
|
+
err0:
|
|
118
|
+
/* Failure! */
|
|
119
|
+
return (NULL);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* We've written our nonce. */
|
|
123
|
+
static int
|
|
124
|
+
callback_nonce_write(void * cookie, ssize_t len)
|
|
125
|
+
{
|
|
126
|
+
struct handshake_cookie * H = cookie;
|
|
127
|
+
|
|
128
|
+
/* This write is no longer pending. */
|
|
129
|
+
H->write_cookie = NULL;
|
|
130
|
+
|
|
131
|
+
/* Did we successfully write? */
|
|
132
|
+
if (len < 32)
|
|
133
|
+
return (handshakefail(H));
|
|
134
|
+
|
|
135
|
+
/* If the nonce read is also done, move on to the next step. */
|
|
136
|
+
if (H->read_cookie == NULL)
|
|
137
|
+
return (gotnonces(H));
|
|
138
|
+
|
|
139
|
+
/* Nothing to do. */
|
|
140
|
+
return (0);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* We've read a nonce. */
|
|
144
|
+
static int
|
|
145
|
+
callback_nonce_read(void * cookie, ssize_t len)
|
|
146
|
+
{
|
|
147
|
+
struct handshake_cookie * H = cookie;
|
|
148
|
+
|
|
149
|
+
/* This read is no longer pending. */
|
|
150
|
+
H->read_cookie = NULL;
|
|
151
|
+
|
|
152
|
+
/* Did we successfully read? */
|
|
153
|
+
if (len < 32)
|
|
154
|
+
return (handshakefail(H));
|
|
155
|
+
|
|
156
|
+
/* If the nonce write is also done, move on to the next step. */
|
|
157
|
+
if (H->write_cookie == NULL)
|
|
158
|
+
return (gotnonces(H));
|
|
159
|
+
|
|
160
|
+
/* Nothing to do. */
|
|
161
|
+
return (0);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* We have two nonces. Start the DH exchange. */
|
|
165
|
+
static int
|
|
166
|
+
gotnonces(struct handshake_cookie * H)
|
|
167
|
+
{
|
|
168
|
+
|
|
169
|
+
/* Compute the diffie-hellman parameter MAC keys. */
|
|
170
|
+
proto_crypt_dhmac(H->K, H->nonce_local, H->nonce_remote,
|
|
171
|
+
H->dhmac_local, H->dhmac_remote, H->decr);
|
|
172
|
+
|
|
173
|
+
/*
|
|
174
|
+
* If we're the server, we need to read the client's diffie-hellman
|
|
175
|
+
* parameter. If we're the client, we need to generate and send our
|
|
176
|
+
* diffie-hellman parameter.
|
|
177
|
+
*/
|
|
178
|
+
if (H->decr)
|
|
179
|
+
return (dhread(H));
|
|
180
|
+
else
|
|
181
|
+
return (dhwrite(H));
|
|
182
|
+
|
|
183
|
+
/* NOTREACHED */
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/* Read a diffie-hellman parameter. */
|
|
187
|
+
static int
|
|
188
|
+
dhread(struct handshake_cookie * H)
|
|
189
|
+
{
|
|
190
|
+
|
|
191
|
+
/* Read the remote signed diffie-hellman parameter. */
|
|
192
|
+
if ((H->read_cookie = network_read(H->s, H->yh_remote, PCRYPT_YH_LEN,
|
|
193
|
+
PCRYPT_YH_LEN, callback_dh_read, H)) == NULL)
|
|
194
|
+
goto err0;
|
|
195
|
+
|
|
196
|
+
/* Success! */
|
|
197
|
+
return (0);
|
|
198
|
+
|
|
199
|
+
err0:
|
|
200
|
+
/* Failure! */
|
|
201
|
+
return (-1);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* We have read a diffie-hellman parameter. */
|
|
205
|
+
static int
|
|
206
|
+
callback_dh_read(void * cookie, ssize_t len)
|
|
207
|
+
{
|
|
208
|
+
struct handshake_cookie * H = cookie;
|
|
209
|
+
|
|
210
|
+
/* This read is no longer pending. */
|
|
211
|
+
H->read_cookie = NULL;
|
|
212
|
+
|
|
213
|
+
/* Did we successfully read? */
|
|
214
|
+
if (len < PCRYPT_YH_LEN)
|
|
215
|
+
return (handshakefail(H));
|
|
216
|
+
|
|
217
|
+
/* Is the value we read valid? */
|
|
218
|
+
if (proto_crypt_dh_validate(H->yh_remote, H->dhmac_remote,
|
|
219
|
+
H->requirefps))
|
|
220
|
+
return (handshakefail(H));
|
|
221
|
+
|
|
222
|
+
/*
|
|
223
|
+
* If we're the server, we need to send our diffie-hellman parameter
|
|
224
|
+
* next. If we're the client, move on to the final computation.
|
|
225
|
+
*/
|
|
226
|
+
if (H->decr)
|
|
227
|
+
return (dhwrite(H));
|
|
228
|
+
else
|
|
229
|
+
return (handshakedone(H));
|
|
230
|
+
|
|
231
|
+
/* NOTREACHED */
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* Generate and write a diffie-hellman parameter. */
|
|
235
|
+
static int
|
|
236
|
+
dhwrite(struct handshake_cookie * H)
|
|
237
|
+
{
|
|
238
|
+
|
|
239
|
+
/* Generate a signed diffie-hellman parameter. */
|
|
240
|
+
if (proto_crypt_dh_generate(H->yh_local, H->x, H->dhmac_local,
|
|
241
|
+
H->nofps))
|
|
242
|
+
goto err0;
|
|
243
|
+
|
|
244
|
+
/* Write our signed diffie-hellman parameter. */
|
|
245
|
+
if ((H->write_cookie = network_write(H->s, H->yh_local, PCRYPT_YH_LEN,
|
|
246
|
+
PCRYPT_YH_LEN, callback_dh_write, H)) == NULL)
|
|
247
|
+
goto err0;
|
|
248
|
+
|
|
249
|
+
/* Success! */
|
|
250
|
+
return (0);
|
|
251
|
+
|
|
252
|
+
err0:
|
|
253
|
+
/* Failure! */
|
|
254
|
+
return (-1);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/* We have written our diffie-hellman parameter. */
|
|
258
|
+
static int
|
|
259
|
+
callback_dh_write(void * cookie, ssize_t len)
|
|
260
|
+
{
|
|
261
|
+
struct handshake_cookie * H = cookie;
|
|
262
|
+
|
|
263
|
+
/* This write is no longer pending. */
|
|
264
|
+
H->write_cookie = NULL;
|
|
265
|
+
|
|
266
|
+
/* Did we successfully write? */
|
|
267
|
+
if (len < PCRYPT_YH_LEN)
|
|
268
|
+
return (handshakefail(H));
|
|
269
|
+
|
|
270
|
+
/*
|
|
271
|
+
* If we're the server, move on to the final computation. If we're
|
|
272
|
+
* the client, we need to read the server's parameter next.
|
|
273
|
+
*/
|
|
274
|
+
if (H->decr)
|
|
275
|
+
return (handshakedone(H));
|
|
276
|
+
else
|
|
277
|
+
return (dhread(H));
|
|
278
|
+
|
|
279
|
+
/* NOTREACHED */
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/* We've got all the bits; do the final computation and callback. */
|
|
283
|
+
static int
|
|
284
|
+
handshakedone(struct handshake_cookie * H)
|
|
285
|
+
{
|
|
286
|
+
struct proto_keys * c;
|
|
287
|
+
struct proto_keys * s;
|
|
288
|
+
int rc;
|
|
289
|
+
|
|
290
|
+
/* Sanity-check: There should be no callbacks in progress. */
|
|
291
|
+
assert(H->read_cookie == NULL);
|
|
292
|
+
assert(H->write_cookie == NULL);
|
|
293
|
+
|
|
294
|
+
/* Perform the final computation. */
|
|
295
|
+
if (proto_crypt_mkkeys(H->K, H->nonce_local, H->nonce_remote,
|
|
296
|
+
H->yh_remote, H->x, H->nofps, H->decr, &c, &s))
|
|
297
|
+
goto err0;
|
|
298
|
+
|
|
299
|
+
/* Perform the callback. */
|
|
300
|
+
rc = (H->callback)(H->cookie, c, s);
|
|
301
|
+
|
|
302
|
+
/* Free the cookie. */
|
|
303
|
+
free(H);
|
|
304
|
+
|
|
305
|
+
/* Return status code from callback. */
|
|
306
|
+
return (rc);
|
|
307
|
+
|
|
308
|
+
err0:
|
|
309
|
+
/* Failure! */
|
|
310
|
+
return (-1);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* proto_handshake_cancel(cookie):
|
|
315
|
+
* Cancel the handshake for which proto_handshake returned ${cookie}.
|
|
316
|
+
*/
|
|
317
|
+
void
|
|
318
|
+
proto_handshake_cancel(void * cookie)
|
|
319
|
+
{
|
|
320
|
+
struct handshake_cookie * H = cookie;
|
|
321
|
+
|
|
322
|
+
/* Cancel any in-progress network operations. */
|
|
323
|
+
if (H->read_cookie != NULL)
|
|
324
|
+
network_read_cancel(H->read_cookie);
|
|
325
|
+
if (H->write_cookie != NULL)
|
|
326
|
+
network_write_cancel(H->write_cookie);
|
|
327
|
+
|
|
328
|
+
/* Free the cookie. */
|
|
329
|
+
free(H);
|
|
330
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#ifndef _PROTO_HANDSHAKE_H_
|
|
2
|
+
#define _PROTO_HANDSHAKE_H_
|
|
3
|
+
|
|
4
|
+
/* Opaque structures. */
|
|
5
|
+
struct proto_keys;
|
|
6
|
+
struct proto_secret;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* proto_handshake(s, decr, nofps, requirefps, K, callback, cookie):
|
|
10
|
+
* Perform a protocol handshake on socket ${s}. If ${decr} is non-zero we are
|
|
11
|
+
* at the receiving end of the connection; otherwise at the sending end. If
|
|
12
|
+
* ${nofps} is non-zero, perform a "weak" handshake without forward perfect
|
|
13
|
+
* secrecy. If ${requirefps} is non-zero, drop the connection if the other
|
|
14
|
+
* end attempts to perform a "weak" handshake. The shared protocol secret is
|
|
15
|
+
* ${K}. Upon completion, invoke ${callback}(${cookie}, f, r), where f
|
|
16
|
+
* contains the keys needed for the forward direction and r contains the keys
|
|
17
|
+
* needed for the reverse direction; or f = r = NULL if the handshake failed.
|
|
18
|
+
* Return a cookie which can be passed to proto_handshake_cancel to cancel the
|
|
19
|
+
* handshake.
|
|
20
|
+
*/
|
|
21
|
+
void * proto_handshake(int, int, int, int, const struct proto_secret *,
|
|
22
|
+
int (*)(void *, struct proto_keys *, struct proto_keys *), void *);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* proto_handshake_cancel(cookie):
|
|
26
|
+
* Cancel the handshake for which proto_handshake returned ${cookie}.
|
|
27
|
+
*/
|
|
28
|
+
void proto_handshake_cancel(void *);
|
|
29
|
+
|
|
30
|
+
#endif /* !_PROTO_HANDSHAKE_H_ */
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
#include <sys/types.h>
|
|
2
|
+
#include <sys/socket.h>
|
|
3
|
+
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
#include <stdlib.h>
|
|
6
|
+
#include <string.h>
|
|
7
|
+
#include <unistd.h>
|
|
8
|
+
|
|
9
|
+
#include "network.h"
|
|
10
|
+
|
|
11
|
+
#include "proto_crypt.h"
|
|
12
|
+
|
|
13
|
+
#include "proto_pipe.h"
|
|
14
|
+
|
|
15
|
+
struct pipe_cookie {
|
|
16
|
+
int (* callback)(void *);
|
|
17
|
+
void * cookie;
|
|
18
|
+
int * status;
|
|
19
|
+
int s_in;
|
|
20
|
+
int s_out;
|
|
21
|
+
int decr;
|
|
22
|
+
struct proto_keys * k;
|
|
23
|
+
uint8_t dbuf[PCRYPT_MAXDSZ];
|
|
24
|
+
uint8_t ebuf[PCRYPT_ESZ];
|
|
25
|
+
void * read_cookie;
|
|
26
|
+
void * write_cookie;
|
|
27
|
+
ssize_t wlen;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
static int callback_pipe_read(void *, ssize_t);
|
|
31
|
+
static int callback_pipe_write(void *, ssize_t);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* proto_pipe(s_in, s_out, decr, k, status, callback, cookie):
|
|
35
|
+
* Read bytes from ${s_in} and write them to ${s_out}. If ${decr} is non-zero
|
|
36
|
+
* then use ${k} to decrypt the bytes; otherwise use ${k} to encrypt them.
|
|
37
|
+
* If EOF is read, set ${status} to 0, and if an error is encountered set
|
|
38
|
+
* ${status} to -1; in either case, invoke ${callback}(${cookie}). Return a
|
|
39
|
+
* cookie which can be passed to proto_pipe_cancel.
|
|
40
|
+
*/
|
|
41
|
+
void *
|
|
42
|
+
proto_pipe(int s_in, int s_out, int decr, struct proto_keys * k,
|
|
43
|
+
int * status, int (* callback)(void *), void * cookie)
|
|
44
|
+
{
|
|
45
|
+
struct pipe_cookie * P;
|
|
46
|
+
|
|
47
|
+
/* Bake a cookie. */
|
|
48
|
+
if ((P = malloc(sizeof(struct pipe_cookie))) == NULL)
|
|
49
|
+
goto err0;
|
|
50
|
+
P->callback = callback;
|
|
51
|
+
P->cookie = cookie;
|
|
52
|
+
P->status = status;
|
|
53
|
+
P->s_in = s_in;
|
|
54
|
+
P->s_out = s_out;
|
|
55
|
+
P->decr = decr;
|
|
56
|
+
P->k = k;
|
|
57
|
+
P->read_cookie = NULL;
|
|
58
|
+
P->write_cookie = NULL;
|
|
59
|
+
|
|
60
|
+
/* Start reading. */
|
|
61
|
+
if (P->decr) {
|
|
62
|
+
if ((P->read_cookie = network_read(P->s_in, P->ebuf,
|
|
63
|
+
PCRYPT_ESZ, PCRYPT_ESZ, callback_pipe_read, P)) == NULL)
|
|
64
|
+
goto err1;
|
|
65
|
+
} else {
|
|
66
|
+
if ((P->read_cookie = network_read(P->s_in, P->dbuf,
|
|
67
|
+
PCRYPT_MAXDSZ, 1, callback_pipe_read, P)) == NULL)
|
|
68
|
+
goto err1;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Success! */
|
|
72
|
+
return (P);
|
|
73
|
+
|
|
74
|
+
err1:
|
|
75
|
+
free(P);
|
|
76
|
+
err0:
|
|
77
|
+
/* Failure! */
|
|
78
|
+
return (NULL);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Some data has been read. */
|
|
82
|
+
static int
|
|
83
|
+
callback_pipe_read(void * cookie, ssize_t len)
|
|
84
|
+
{
|
|
85
|
+
struct pipe_cookie * P = cookie;
|
|
86
|
+
|
|
87
|
+
/* This read is no longer in progress. */
|
|
88
|
+
P->read_cookie = NULL;
|
|
89
|
+
|
|
90
|
+
/* Did we read EOF? */
|
|
91
|
+
if (len == 0)
|
|
92
|
+
goto eof;
|
|
93
|
+
|
|
94
|
+
/* Did the read fail? */
|
|
95
|
+
if (len == -1)
|
|
96
|
+
goto fail;
|
|
97
|
+
|
|
98
|
+
/* Did a packet read end prematurely? */
|
|
99
|
+
if ((P->decr) && (len < PCRYPT_ESZ))
|
|
100
|
+
goto fail;
|
|
101
|
+
|
|
102
|
+
/* Encrypt or decrypt the data. */
|
|
103
|
+
if (P->decr) {
|
|
104
|
+
if ((P->wlen = proto_crypt_dec(P->ebuf, P->dbuf, P->k)) == -1)
|
|
105
|
+
goto fail;
|
|
106
|
+
} else {
|
|
107
|
+
proto_crypt_enc(P->dbuf, len, P->ebuf, P->k);
|
|
108
|
+
P->wlen = PCRYPT_ESZ;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Write the encrypted or decrypted data. */
|
|
112
|
+
if (P->decr) {
|
|
113
|
+
if ((P->write_cookie = network_write(P->s_out, P->dbuf,
|
|
114
|
+
P->wlen, P->wlen, callback_pipe_write, P)) == NULL)
|
|
115
|
+
goto err0;
|
|
116
|
+
} else {
|
|
117
|
+
if ((P->write_cookie = network_write(P->s_out, P->ebuf,
|
|
118
|
+
P->wlen, P->wlen, callback_pipe_write, P)) == NULL)
|
|
119
|
+
goto err0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* Success! */
|
|
123
|
+
return (0);
|
|
124
|
+
|
|
125
|
+
fail:
|
|
126
|
+
/* Record that this connection is broken. */
|
|
127
|
+
*(P->status) = -1;
|
|
128
|
+
|
|
129
|
+
/* Inform the upstream that our status has changed. */
|
|
130
|
+
return ((P->callback)(P->cookie));
|
|
131
|
+
|
|
132
|
+
eof:
|
|
133
|
+
/* We aren't going to write any more. */
|
|
134
|
+
shutdown(P->s_out, SHUT_WR);
|
|
135
|
+
|
|
136
|
+
/* Record that we have reached EOF. */
|
|
137
|
+
*(P->status) = 0;
|
|
138
|
+
|
|
139
|
+
/* Inform the upstream that our status has changed. */
|
|
140
|
+
return ((P->callback)(P->cookie));
|
|
141
|
+
|
|
142
|
+
err0:
|
|
143
|
+
/* Failure! */
|
|
144
|
+
return (-1);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
static int
|
|
148
|
+
callback_pipe_write(void * cookie, ssize_t len)
|
|
149
|
+
{
|
|
150
|
+
struct pipe_cookie * P = cookie;
|
|
151
|
+
|
|
152
|
+
/* This write is no longer in progress. */
|
|
153
|
+
P->write_cookie = NULL;
|
|
154
|
+
|
|
155
|
+
/* Did we fail to write everything? */
|
|
156
|
+
if (len < P->wlen)
|
|
157
|
+
goto fail;
|
|
158
|
+
|
|
159
|
+
/* Launch another read. */
|
|
160
|
+
if (P->decr) {
|
|
161
|
+
if ((P->read_cookie = network_read(P->s_in, P->ebuf,
|
|
162
|
+
PCRYPT_ESZ, PCRYPT_ESZ, callback_pipe_read, P)) == NULL)
|
|
163
|
+
goto err0;
|
|
164
|
+
} else {
|
|
165
|
+
if ((P->read_cookie = network_read(P->s_in, P->dbuf,
|
|
166
|
+
PCRYPT_MAXDSZ, 1, callback_pipe_read, P)) == NULL)
|
|
167
|
+
goto err0;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* Success! */
|
|
171
|
+
return (0);
|
|
172
|
+
|
|
173
|
+
fail:
|
|
174
|
+
/* Record that this connection is broken. */
|
|
175
|
+
*(P->status) = -1;
|
|
176
|
+
|
|
177
|
+
/* Inform the upstream that our status has changed. */
|
|
178
|
+
return ((P->callback)(P->cookie));
|
|
179
|
+
|
|
180
|
+
err0:
|
|
181
|
+
/* Failure! */
|
|
182
|
+
return (-1);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* proto_pipe_cancel(cookie):
|
|
187
|
+
* Shut down the pipe created by proto_pipe for which ${cookie} was returned.
|
|
188
|
+
*/
|
|
189
|
+
void
|
|
190
|
+
proto_pipe_cancel(void * cookie)
|
|
191
|
+
{
|
|
192
|
+
struct pipe_cookie * P = cookie;
|
|
193
|
+
|
|
194
|
+
/* If a read or write is in progress, cancel it. */
|
|
195
|
+
if (P->read_cookie)
|
|
196
|
+
network_read_cancel(P->read_cookie);
|
|
197
|
+
if (P->write_cookie)
|
|
198
|
+
network_write_cancel(P->write_cookie);
|
|
199
|
+
|
|
200
|
+
/* Free the cookie. */
|
|
201
|
+
free(P);
|
|
202
|
+
}
|