diff options
Diffstat (limited to 'nacl/curvecp/curvecpserver.c')
-rw-r--r-- | nacl/curvecp/curvecpserver.c | 497 |
1 files changed, 497 insertions, 0 deletions
diff --git a/nacl/curvecp/curvecpserver.c b/nacl/curvecp/curvecpserver.c new file mode 100644 index 00000000..82cc6670 --- /dev/null +++ b/nacl/curvecp/curvecpserver.c | |||
@@ -0,0 +1,497 @@ | |||
1 | #include <signal.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <sys/types.h> | ||
4 | #include <sys/stat.h> | ||
5 | #include <fcntl.h> | ||
6 | #include <unistd.h> | ||
7 | #include <poll.h> | ||
8 | #include "e.h" | ||
9 | #include "die.h" | ||
10 | #include "byte.h" | ||
11 | #include "open.h" | ||
12 | #include "load.h" | ||
13 | #include "socket.h" | ||
14 | #include "uint64_pack.h" | ||
15 | #include "uint64_unpack.h" | ||
16 | #include "writeall.h" | ||
17 | #include "nanoseconds.h" | ||
18 | #include "safenonce.h" | ||
19 | #include "nameparse.h" | ||
20 | #include "hexparse.h" | ||
21 | #include "portparse.h" | ||
22 | #include "randommod.h" | ||
23 | |||
24 | #include "randombytes.h" | ||
25 | #include "crypto_box.h" | ||
26 | #include "crypto_secretbox.h" | ||
27 | #if crypto_box_PUBLICKEYBYTES != 32 | ||
28 | error! | ||
29 | #endif | ||
30 | #if crypto_box_NONCEBYTES != 24 | ||
31 | error! | ||
32 | #endif | ||
33 | #if crypto_box_BOXZEROBYTES != 16 | ||
34 | error! | ||
35 | #endif | ||
36 | #if crypto_box_ZEROBYTES != 32 | ||
37 | error! | ||
38 | #endif | ||
39 | #if crypto_box_BEFORENMBYTES != 32 | ||
40 | error! | ||
41 | #endif | ||
42 | #if crypto_secretbox_KEYBYTES != 32 | ||
43 | error! | ||
44 | #endif | ||
45 | #if crypto_secretbox_NONCEBYTES != 24 | ||
46 | error! | ||
47 | #endif | ||
48 | #if crypto_secretbox_BOXZEROBYTES != 16 | ||
49 | error! | ||
50 | #endif | ||
51 | #if crypto_secretbox_ZEROBYTES != 32 | ||
52 | error! | ||
53 | #endif | ||
54 | |||
55 | int flagverbose; | ||
56 | |||
57 | #define USAGE "\ | ||
58 | curvecpserver: how to use:\n\ | ||
59 | curvecpserver: -q (optional): no error messages\n\ | ||
60 | curvecpserver: -Q (optional): print error messages (default)\n\ | ||
61 | curvecpserver: -v (optional): print extra information\n\ | ||
62 | curvecpserver: -c n (optional): allow at most n clients at once (default 100)\n\ | ||
63 | curvecpserver: sname: server's name\n\ | ||
64 | curvecpserver: keydir: use this public-key directory\n\ | ||
65 | curvecpserver: ip: server's IP address\n\ | ||
66 | curvecpserver: port: server's UDP port\n\ | ||
67 | curvecpserver: ext: server's extension\n\ | ||
68 | curvecpserver: prog: run this server\n\ | ||
69 | " | ||
70 | |||
71 | void die_usage(const char *s) | ||
72 | { | ||
73 | if (s) die_4(100,USAGE,"curvecpserver: fatal: ",s,"\n"); | ||
74 | die_1(100,USAGE); | ||
75 | } | ||
76 | |||
77 | void die_fatal(const char *trouble,const char *d,const char *fn) | ||
78 | { | ||
79 | if (!flagverbose) die_0(111); | ||
80 | if (d) { | ||
81 | if (fn) die_9(111,"curvecpserver: fatal: ",trouble," ",d,"/",fn,": ",e_str(errno),"\n"); | ||
82 | die_7(111,"curvecpserver: fatal: ",trouble," ",d,": ",e_str(errno),"\n"); | ||
83 | } | ||
84 | die_5(111,"curvecpserver: fatal: ",trouble,": ",e_str(errno),"\n"); | ||
85 | } | ||
86 | |||
87 | int ipparse(unsigned char *y,const char *x) | ||
88 | { | ||
89 | long long j; | ||
90 | long long k; | ||
91 | long long d; | ||
92 | |||
93 | for (k = 0;k < 4;++k) y[k] = 0; | ||
94 | for (k = 0;k < 4;++k) { | ||
95 | d = 0; | ||
96 | for (j = 0;j < 3 && x[j] >= '0' && x[j] <= '9';++j) d = d * 10 + (x[j] - '0'); | ||
97 | if (j == 0) return 0; | ||
98 | x += j; | ||
99 | if (k >= 0 && k < 4) y[k] = d; | ||
100 | if (k < 3) { | ||
101 | if (*x != '.') return 0; | ||
102 | ++x; | ||
103 | } | ||
104 | } | ||
105 | if (*x) return 0; | ||
106 | return 1; | ||
107 | } | ||
108 | |||
109 | int maxparse(long long *y,const char *x) | ||
110 | { | ||
111 | long long d; | ||
112 | long long j; | ||
113 | |||
114 | d = 0; | ||
115 | for (j = 0;j < 9 && x[j] >= '0' && x[j] <= '9';++j) d = d * 10 + (x[j] - '0'); | ||
116 | if (x[j]) return 0; | ||
117 | if (d < 1) return 0; | ||
118 | if (d > 65535) return 0; | ||
119 | *y = d; | ||
120 | return 1; | ||
121 | } | ||
122 | |||
123 | /* cookies: */ | ||
124 | long long nextminute; | ||
125 | unsigned char minutekey[32]; | ||
126 | unsigned char lastminutekey[32]; | ||
127 | |||
128 | /* routing to the server: */ | ||
129 | unsigned char serverip[4]; | ||
130 | unsigned char serverport[2]; | ||
131 | unsigned char serverextension[16]; | ||
132 | int udpfd = -1; | ||
133 | |||
134 | /* server security: */ | ||
135 | char *keydir = 0; | ||
136 | unsigned char servername[256]; | ||
137 | unsigned char serverlongtermsk[32]; | ||
138 | unsigned char servershorttermpk[32]; | ||
139 | unsigned char servershorttermsk[32]; | ||
140 | |||
141 | /* routing to the client: */ | ||
142 | unsigned char clientextension[16]; | ||
143 | |||
144 | /* client security: */ | ||
145 | unsigned char clientlongtermpk[32]; | ||
146 | unsigned char clientshorttermpk[32]; | ||
147 | |||
148 | /* shared secrets: */ | ||
149 | unsigned char clientshortserverlong[32]; | ||
150 | unsigned char clientshortservershort[32]; | ||
151 | unsigned char clientlongserverlong[32]; | ||
152 | |||
153 | unsigned char allzero[128] = {0}; | ||
154 | |||
155 | unsigned char nonce[24]; | ||
156 | unsigned char text[2048]; | ||
157 | |||
158 | unsigned char packetip[4]; | ||
159 | unsigned char packetport[2]; | ||
160 | unsigned char packet[4096]; | ||
161 | crypto_uint64 packetnonce; | ||
162 | |||
163 | #define MESSAGELEN 1104 | ||
164 | |||
165 | struct activeclient { | ||
166 | unsigned char clientshorttermpk[32]; | ||
167 | unsigned char clientshortservershort[32]; | ||
168 | crypto_uint64 receivednonce; | ||
169 | crypto_uint64 sentnonce; | ||
170 | long long messagelen; | ||
171 | pid_t child; | ||
172 | int tochild; | ||
173 | int fromchild; | ||
174 | unsigned char clientextension[16]; | ||
175 | unsigned char clientip[4]; | ||
176 | unsigned char clientport[2]; | ||
177 | unsigned char message[MESSAGELEN]; | ||
178 | } ; | ||
179 | |||
180 | const char *strmaxactiveclients = "100"; | ||
181 | long long maxactiveclients = 0; | ||
182 | long long numactiveclients = 0; | ||
183 | struct activeclient *activeclients = 0; | ||
184 | struct pollfd *p; | ||
185 | |||
186 | int fdwd = -1; | ||
187 | |||
188 | int pi0[2]; | ||
189 | int pi1[2]; | ||
190 | |||
191 | unsigned char childbuf[4096]; | ||
192 | long long childbuflen = 0; | ||
193 | unsigned char childmessage[2048]; | ||
194 | long long childmessagelen = 0; | ||
195 | |||
196 | int main(int argc,char **argv) | ||
197 | { | ||
198 | long long r; | ||
199 | long long i; | ||
200 | long long k; | ||
201 | |||
202 | signal(SIGPIPE,SIG_IGN); | ||
203 | signal(SIGCHLD,SIG_IGN); | ||
204 | |||
205 | if (!argv[0]) die_usage(0); | ||
206 | for (;;) { | ||
207 | char *x; | ||
208 | if (!argv[1]) break; | ||
209 | if (argv[1][0] != '-') break; | ||
210 | x = *++argv; | ||
211 | if (x[0] == '-' && x[1] == 0) break; | ||
212 | if (x[0] == '-' && x[1] == '-' && x[2] == 0) break; | ||
213 | while (*++x) { | ||
214 | if (*x == 'q') { flagverbose = 0; continue; } | ||
215 | if (*x == 'Q') { flagverbose = 1; continue; } | ||
216 | if (*x == 'v') { if (flagverbose == 2) flagverbose = 3; else flagverbose = 2; continue; } | ||
217 | if (*x == 'c') { | ||
218 | if (x[1]) { strmaxactiveclients = x + 1; break; } | ||
219 | if (argv[1]) { strmaxactiveclients = *++argv; break; } | ||
220 | } | ||
221 | die_usage(0); | ||
222 | } | ||
223 | } | ||
224 | if (!maxparse(&maxactiveclients,strmaxactiveclients)) die_usage("concurrency must be between 1 and 65535"); | ||
225 | if (!nameparse(servername,*++argv)) die_usage("sname must be at most 255 bytes, at most 63 bytes between dots"); | ||
226 | keydir = *++argv; if (!keydir) die_usage("missing keydir"); | ||
227 | if (!ipparse(serverip,*++argv)) die_usage("ip must be an IPv4 address"); | ||
228 | if (!portparse(serverport,*++argv)) die_usage("port must be an integer between 0 and 65535"); | ||
229 | if (!hexparse(serverextension,16,*++argv)) die_usage("ext must be exactly 32 hex characters"); | ||
230 | if (!*++argv) die_usage("missing prog"); | ||
231 | |||
232 | for (;;) { | ||
233 | r = open_read("/dev/null"); | ||
234 | if (r == -1) die_fatal("unable to open /dev/null",0,0); | ||
235 | if (r > 9) { close(r); break; } | ||
236 | } | ||
237 | |||
238 | activeclients = malloc(maxactiveclients * sizeof(struct activeclient)); | ||
239 | if (!activeclients) die_fatal("unable to create activeclients array",0,0); | ||
240 | randombytes((void *) activeclients,maxactiveclients * sizeof(struct activeclient)); | ||
241 | for (i = 0;i < maxactiveclients;++i) { | ||
242 | activeclients[i].child = -1; | ||
243 | activeclients[i].tochild = -1; | ||
244 | activeclients[i].fromchild = -1; | ||
245 | activeclients[i].receivednonce = 0; | ||
246 | activeclients[i].sentnonce = randommod(281474976710656LL); | ||
247 | } | ||
248 | |||
249 | p = malloc((1 + maxactiveclients) * sizeof(struct pollfd)); | ||
250 | if (!p) die_fatal("unable to create poll array",0,0); | ||
251 | |||
252 | fdwd = open_cwd(); | ||
253 | if (fdwd == -1) die_fatal("unable to open current directory",0,0); | ||
254 | |||
255 | if (chdir(keydir) == -1) die_fatal("unable to chdir to",keydir,0); | ||
256 | if (load(".expertsonly/secretkey",serverlongtermsk,sizeof serverlongtermsk) == -1) die_fatal("unable to read secret key from",keydir,0); | ||
257 | |||
258 | udpfd = socket_udp(); | ||
259 | if (udpfd == -1) die_fatal("unable to create socket",0,0); | ||
260 | if (socket_bind(udpfd,serverip,serverport) == -1) die_fatal("unable to bind socket",0,0); | ||
261 | |||
262 | randombytes(minutekey,sizeof minutekey); | ||
263 | randombytes(lastminutekey,sizeof lastminutekey); | ||
264 | nextminute = nanoseconds() + 60000000000ULL; | ||
265 | |||
266 | for (;;) { | ||
267 | long long timeout = nextminute - nanoseconds(); | ||
268 | if (timeout <= 0) { | ||
269 | timeout = 60000000000ULL; | ||
270 | byte_copy(lastminutekey,sizeof lastminutekey,minutekey); | ||
271 | randombytes(minutekey,sizeof minutekey); | ||
272 | nextminute = nanoseconds() + timeout; | ||
273 | randombytes(packet,sizeof packet); | ||
274 | randombytes(packetip,sizeof packetip); | ||
275 | randombytes(packetport,sizeof packetport); | ||
276 | randombytes(clientshorttermpk,sizeof clientshorttermpk); | ||
277 | randombytes(clientshortserverlong,sizeof clientshortserverlong); | ||
278 | randombytes(nonce,sizeof nonce); | ||
279 | randombytes(text,sizeof text); | ||
280 | randombytes(childbuf,sizeof childbuf); | ||
281 | randombytes(childmessage,sizeof childmessage); | ||
282 | randombytes(servershorttermpk,sizeof servershorttermpk); | ||
283 | randombytes(servershorttermsk,sizeof servershorttermsk); | ||
284 | } | ||
285 | |||
286 | for (i = 0;i < numactiveclients;++i) { | ||
287 | p[i].fd = activeclients[i].fromchild; | ||
288 | p[i].events = POLLIN; | ||
289 | } | ||
290 | p[numactiveclients].fd = udpfd; | ||
291 | p[numactiveclients].events = POLLIN; | ||
292 | if (poll(p,1 + numactiveclients,timeout / 1000000 + 1) < 0) continue; | ||
293 | |||
294 | do { /* try receiving a packet: */ | ||
295 | if (!p[numactiveclients].revents) break; | ||
296 | r = socket_recv(udpfd,packet,sizeof packet,packetip,packetport); | ||
297 | if (r < 80) break; | ||
298 | if (r > 1184) break; | ||
299 | if (r & 15) break; | ||
300 | if (!(byte_isequal(packet,7,"QvnQ5Xl") & byte_isequal(packet + 8,16,serverextension))) break; | ||
301 | byte_copy(clientextension,16,packet + 24); | ||
302 | if (packet[7] == 'H') { /* Hello packet: */ | ||
303 | if (r != 224) break; | ||
304 | byte_copy(clientshorttermpk,32,packet + 40); | ||
305 | crypto_box_beforenm(clientshortserverlong,clientshorttermpk,serverlongtermsk); | ||
306 | byte_copy(nonce,16,"CurveCP-client-H"); | ||
307 | byte_copy(nonce + 16,8,packet + 136); | ||
308 | byte_zero(text,16); | ||
309 | byte_copy(text + 16,80,packet + 144); | ||
310 | if (crypto_box_open_afternm(text,text,96,nonce,clientshortserverlong)) break; | ||
311 | |||
312 | /* send Cookie packet: */ | ||
313 | |||
314 | crypto_box_keypair(servershorttermpk,servershorttermsk); | ||
315 | byte_zero(text + 64,32); | ||
316 | byte_copy(text + 96,32,clientshorttermpk); | ||
317 | byte_copy(text + 128,32,servershorttermsk); | ||
318 | byte_copy(nonce,8,"minute-k"); | ||
319 | if (safenonce(nonce + 8,1) == -1) die_fatal("nonce-generation disaster",0,0); | ||
320 | crypto_secretbox(text + 64,text + 64,96,nonce,minutekey); | ||
321 | byte_copy(text + 64,16,nonce + 8); | ||
322 | |||
323 | byte_zero(text,32); | ||
324 | byte_copy(text + 32,32,servershorttermpk); | ||
325 | byte_copy(nonce,8,"CurveCPK"); /* reusing the other 16 bytes */ | ||
326 | crypto_box_afternm(text,text,160,nonce,clientshortserverlong); | ||
327 | |||
328 | byte_copy(packet,8,"RL3aNMXK"); | ||
329 | byte_copy(packet + 8,16,clientextension); | ||
330 | byte_copy(packet + 24,16,serverextension); | ||
331 | byte_copy(packet + 40,16,nonce + 8); | ||
332 | byte_copy(packet + 56,144,text + 16); | ||
333 | |||
334 | socket_send(udpfd,packet,200,packetip,packetport); | ||
335 | } | ||
336 | if (packet[7] == 'I') { /* Initiate packet: */ | ||
337 | if (r < 560) break; | ||
338 | for (i = 0;i < numactiveclients;++i) /* XXX use better data structure */ | ||
339 | if (byte_isequal(activeclients[i].clientshorttermpk,32,packet + 40)) | ||
340 | break; | ||
341 | if (i < numactiveclients) { | ||
342 | packetnonce = uint64_unpack(packet + 168); | ||
343 | if (packetnonce <= activeclients[i].receivednonce) break; | ||
344 | byte_copy(nonce,16,"CurveCP-client-I"); | ||
345 | byte_copy(nonce + 16,8,packet + 168); | ||
346 | byte_zero(text,16); | ||
347 | byte_copy(text + 16,r - 176,packet + 176); | ||
348 | if (crypto_box_open_afternm(text,text,r - 160,nonce,activeclients[i].clientshortservershort)) break; | ||
349 | |||
350 | /* XXX: update clientip, clientextension; but not if client has spoken recently */ | ||
351 | activeclients[i].receivednonce = packetnonce; | ||
352 | text[383] = (r - 544) >> 4; | ||
353 | if (writeall(activeclients[i].tochild,text + 383,r - 543) == -1) | ||
354 | ; /* child is gone; will see eof later */ | ||
355 | break; | ||
356 | } | ||
357 | if (i == maxactiveclients) break; | ||
358 | |||
359 | byte_copy(nonce,8,"minute-k"); | ||
360 | byte_copy(nonce + 8,16,packet + 72); | ||
361 | byte_zero(text,16); | ||
362 | byte_copy(text + 16,80,packet + 88); | ||
363 | if (crypto_secretbox_open(text,text,96,nonce,minutekey)) { | ||
364 | byte_zero(text,16); | ||
365 | byte_copy(text + 16,80,packet + 88); | ||
366 | if (crypto_secretbox_open(text,text,96,nonce,lastminutekey)) break; | ||
367 | } | ||
368 | if (!byte_isequal(packet + 40,32,text + 32)) break; | ||
369 | byte_copy(servershorttermsk,32,text + 64); | ||
370 | byte_copy(clientshorttermpk,32,packet + 40); | ||
371 | crypto_box_beforenm(clientshortservershort,clientshorttermpk,servershorttermsk); | ||
372 | |||
373 | byte_copy(nonce,16,"CurveCP-client-I"); | ||
374 | byte_copy(nonce + 16,8,packet + 168); | ||
375 | byte_zero(text,16); | ||
376 | byte_copy(text + 16,r - 176,packet + 176); | ||
377 | if (crypto_box_open_afternm(text,text,r - 160,nonce,clientshortservershort)) break; | ||
378 | |||
379 | if (!byte_isequal(text + 128,256,servername)) break; | ||
380 | |||
381 | /* XXX skip if client authentication is not desired: */ | ||
382 | byte_copy(clientlongtermpk,32,text + 32); | ||
383 | /* XXX impose policy limitations on clients: known, maxconn */ | ||
384 | /* XXX for known clients, retrieve shared secret from cache: */ | ||
385 | crypto_box_beforenm(clientlongserverlong,clientlongtermpk,serverlongtermsk); | ||
386 | byte_copy(nonce,8,"CurveCPV"); | ||
387 | byte_copy(nonce + 8,16,text + 64); | ||
388 | byte_zero(text + 64,16); | ||
389 | if (crypto_box_open_afternm(text + 64,text + 64,64,nonce,clientlongserverlong)) break; | ||
390 | if (!byte_isequal(text + 96,32,clientshorttermpk)) break; | ||
391 | |||
392 | if (open_pipe(pi0) == -1) break; /* XXX: error message */ | ||
393 | if (open_pipe(pi1) == -1) { close(pi0[0]); close(pi0[1]); break; } /* XXX: error message */ | ||
394 | |||
395 | activeclients[i].child = fork(); | ||
396 | if (activeclients[i].child == -1) { | ||
397 | close(pi0[0]); close(pi0[1]); | ||
398 | close(pi1[0]); close(pi1[1]); | ||
399 | break; /* XXX: error message */ | ||
400 | } | ||
401 | if (activeclients[i].child == 0) { | ||
402 | if (fchdir(fdwd) == -1) die_fatal("unable to chdir to original directory",0,0); | ||
403 | close(8); | ||
404 | if (dup(pi0[0]) != 8) die_fatal("unable to dup",0,0); | ||
405 | close(9); | ||
406 | if (dup(pi1[1]) != 9) die_fatal("unable to dup",0,0); | ||
407 | /* XXX: set up environment variables */ | ||
408 | signal(SIGPIPE,SIG_DFL); | ||
409 | signal(SIGCHLD,SIG_DFL); | ||
410 | execvp(*argv,argv); | ||
411 | die_fatal("unable to run",*argv,0); | ||
412 | } | ||
413 | |||
414 | activeclients[i].tochild = pi0[1]; close(pi0[0]); | ||
415 | activeclients[i].fromchild = pi1[0]; close(pi1[1]); | ||
416 | activeclients[i].messagelen = 0; | ||
417 | byte_copy(activeclients[i].clientshorttermpk,32,clientshorttermpk); | ||
418 | byte_copy(activeclients[i].clientshortservershort,32,clientshortservershort); | ||
419 | activeclients[i].receivednonce = uint64_unpack(packet + 168); | ||
420 | byte_copy(activeclients[i].clientextension,16,clientextension); | ||
421 | byte_copy(activeclients[i].clientip,4,packetip); | ||
422 | byte_copy(activeclients[i].clientport,2,packetport); | ||
423 | ++numactiveclients; | ||
424 | |||
425 | text[383] = (r - 544) >> 4; | ||
426 | if (writeall(activeclients[i].tochild,text + 383,r - 543) == -1) | ||
427 | ; /* child is gone; will see eof later */ | ||
428 | } | ||
429 | if (packet[7] == 'M') { /* Message packet: */ | ||
430 | if (r < 112) break; | ||
431 | for (i = 0;i < numactiveclients;++i) /* XXX use better data structure */ | ||
432 | if (byte_isequal(activeclients[i].clientshorttermpk,32,packet + 40)) | ||
433 | break; | ||
434 | if (i < numactiveclients) { | ||
435 | packetnonce = uint64_unpack(packet + 72); | ||
436 | if (packetnonce <= activeclients[i].receivednonce) break; | ||
437 | byte_copy(nonce,16,"CurveCP-client-M"); | ||
438 | byte_copy(nonce + 16,8,packet + 72); | ||
439 | byte_zero(text,16); | ||
440 | byte_copy(text + 16,r - 80,packet + 80); | ||
441 | if (crypto_box_open_afternm(text,text,r - 64,nonce,activeclients[i].clientshortservershort)) break; | ||
442 | |||
443 | /* XXX: update clientip, clientextension */ | ||
444 | activeclients[i].receivednonce = packetnonce; | ||
445 | text[31] = (r - 96) >> 4; | ||
446 | if (writeall(activeclients[i].tochild,text + 31,r - 95) == -1) | ||
447 | ; /* child is gone; will see eof later */ | ||
448 | break; | ||
449 | } | ||
450 | } | ||
451 | } while (0); | ||
452 | |||
453 | for (i = numactiveclients - 1;i >= 0;--i) { | ||
454 | do { | ||
455 | if (!p[i].revents) break; | ||
456 | r = read(activeclients[i].fromchild,childbuf,sizeof childbuf); | ||
457 | if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break; | ||
458 | if (r <= 0) goto endconnection; | ||
459 | childbuflen = r; | ||
460 | for (k = 0;k < childbuflen;++k) { | ||
461 | r = activeclients[i].messagelen; | ||
462 | if (r < 0) goto endconnection; | ||
463 | if (r >= MESSAGELEN) goto endconnection; | ||
464 | activeclients[i].message[r] = childbuf[k]; | ||
465 | if (r == 0) if (childbuf[k] & 128) goto endconnection; | ||
466 | activeclients[i].messagelen = r + 1; | ||
467 | if (r == 16 * (unsigned long long) activeclients[i].message[0]) { | ||
468 | if (r < 16) goto endconnection; | ||
469 | if (r > 1088) goto endconnection; | ||
470 | byte_copy(nonce,16,"CurveCP-server-M"); | ||
471 | uint64_pack(nonce + 16,++activeclients[i].sentnonce); | ||
472 | byte_zero(text,32); | ||
473 | byte_copy(text + 32,r,activeclients[i].message + 1); | ||
474 | crypto_box_afternm(text,text,r + 32,nonce,activeclients[i].clientshortservershort); | ||
475 | byte_copy(packet,8,"RL3aNMXM"); | ||
476 | byte_copy(packet + 8,16,clientextension); | ||
477 | byte_copy(packet + 24,16,serverextension); | ||
478 | byte_copy(packet + 40,8,nonce + 16); | ||
479 | byte_copy(packet + 48,r + 16,text + 16); | ||
480 | socket_send(udpfd,packet,r + 64,activeclients[i].clientip,activeclients[i].clientport); | ||
481 | activeclients[i].messagelen = 0; | ||
482 | } | ||
483 | } | ||
484 | break; | ||
485 | |||
486 | endconnection: | ||
487 | |||
488 | /* XXX: cache cookie if it's recent */ | ||
489 | close(activeclients[i].fromchild); activeclients[i].fromchild = -1; | ||
490 | close(activeclients[i].tochild); activeclients[i].tochild = -1; | ||
491 | --numactiveclients; | ||
492 | activeclients[i] = activeclients[numactiveclients]; | ||
493 | randombytes((void *) &activeclients[numactiveclients],sizeof(struct activeclient)); | ||
494 | } while (0); | ||
495 | } | ||
496 | } | ||
497 | } | ||