1
0

curvecpserver.c 16 KB

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