Kromek Radangel gamma spectrometer USB HID daemon and WebUI. https://git.unino.de/pvivell/radangel
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. /*
  2. * WebSocket lib with support for "wss://" encryption.
  3. * Copyright 2010 Joel Martin
  4. * Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
  5. *
  6. * You can make a cert/key with openssl using:
  7. * openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
  8. * as taken from http://docs.python.org/dev/library/ssl.html#certificates
  9. */
  10. #include <unistd.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <errno.h>
  14. #include <strings.h>
  15. #include <sys/types.h>
  16. #include <sys/socket.h>
  17. #include <sys/stat.h>
  18. #include <netinet/in.h>
  19. #include <arpa/inet.h>
  20. #include <netdb.h>
  21. #include <signal.h> // daemonizing
  22. #include <fcntl.h> // daemonizing
  23. #include <openssl/err.h>
  24. #include <openssl/ssl.h>
  25. #include <openssl/md5.h> /* md5 hash */
  26. #include <openssl/sha.h> /* sha1 hash */
  27. #include "websocket.h"
  28. int ws_b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize);
  29. int ws_b64_pton(char const *src, u_char *target, size_t targsize);
  30. /*
  31. * Global state
  32. *
  33. * Warning: not thread safe
  34. */
  35. int ssl_initialized = 0;
  36. int pipe_error = 0;
  37. settings_t settings;
  38. void traffic(const char * token) {
  39. if ((settings.verbose) && (! settings.daemon)) {
  40. fprintf(stdout, "%s", token);
  41. fflush(stdout);
  42. }
  43. }
  44. void error(char *msg)
  45. {
  46. perror(msg);
  47. }
  48. void fatal(char *msg)
  49. {
  50. perror(msg);
  51. exit(1);
  52. }
  53. /* resolve host with also IP address parsing */
  54. int resolve_host(struct in_addr *sin_addr, const char *hostname)
  55. {
  56. if (!inet_aton(hostname, sin_addr)) {
  57. struct addrinfo *ai, *cur;
  58. struct addrinfo hints;
  59. memset(&hints, 0, sizeof(hints));
  60. hints.ai_family = AF_INET;
  61. if (getaddrinfo(hostname, NULL, &hints, &ai))
  62. return -1;
  63. for (cur = ai; cur; cur = cur->ai_next) {
  64. if (cur->ai_family == AF_INET) {
  65. *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
  66. freeaddrinfo(ai);
  67. return 0;
  68. }
  69. }
  70. freeaddrinfo(ai);
  71. return -1;
  72. }
  73. return 0;
  74. }
  75. /*
  76. * SSL Wrapper Code
  77. */
  78. ssize_t ws_recv(ws_ctx_t *ctx, void *buf, size_t len) {
  79. if (ctx->ssl) {
  80. //handler_msg("SSL recv\n");
  81. return SSL_read(ctx->ssl, buf, len);
  82. } else {
  83. return recv(ctx->sockfd, buf, len, 0);
  84. }
  85. }
  86. ssize_t ws_send(ws_ctx_t *ctx, const void *buf, size_t len) {
  87. if (ctx->ssl) {
  88. //handler_msg("SSL send\n");
  89. return SSL_write(ctx->ssl, buf, len);
  90. } else {
  91. return send(ctx->sockfd, buf, len, 0);
  92. }
  93. }
  94. ws_ctx_t *alloc_ws_ctx() {
  95. ws_ctx_t *ctx;
  96. if (! (ctx = malloc(sizeof(ws_ctx_t))) )
  97. { fatal("malloc()"); }
  98. if (! (ctx->cin_buf = malloc(BUFSIZE)) )
  99. { fatal("malloc of cin_buf"); }
  100. if (! (ctx->cout_buf = malloc(BUFSIZE)) )
  101. { fatal("malloc of cout_buf"); }
  102. if (! (ctx->tin_buf = malloc(BUFSIZE)) )
  103. { fatal("malloc of tin_buf"); }
  104. if (! (ctx->tout_buf = malloc(BUFSIZE)) )
  105. { fatal("malloc of tout_buf"); }
  106. ctx->headers = malloc(sizeof(headers_t));
  107. ctx->ssl = NULL;
  108. ctx->ssl_ctx = NULL;
  109. return ctx;
  110. }
  111. void free_ws_ctx(ws_ctx_t *ctx) {
  112. free(ctx->cin_buf);
  113. free(ctx->cout_buf);
  114. free(ctx->tin_buf);
  115. free(ctx->tout_buf);
  116. free(ctx);
  117. }
  118. ws_ctx_t *ws_socket(ws_ctx_t *ctx, int socket) {
  119. ctx->sockfd = socket;
  120. return ctx;
  121. }
  122. ws_ctx_t *ws_socket_ssl(ws_ctx_t *ctx, int socket, char * certfile, char * keyfile) {
  123. int ret;
  124. char msg[1024];
  125. char * use_keyfile;
  126. ws_socket(ctx, socket);
  127. if (keyfile && (keyfile[0] != '\0')) {
  128. // Separate key file
  129. use_keyfile = keyfile;
  130. } else {
  131. // Combined key and cert file
  132. use_keyfile = certfile;
  133. }
  134. // Initialize the library
  135. if (! ssl_initialized) {
  136. SSL_library_init();
  137. OpenSSL_add_all_algorithms();
  138. SSL_load_error_strings();
  139. ssl_initialized = 1;
  140. }
  141. ctx->ssl_ctx = SSL_CTX_new(TLSv1_server_method());
  142. if (ctx->ssl_ctx == NULL) {
  143. ERR_print_errors_fp(stderr);
  144. fatal("Failed to configure SSL context");
  145. }
  146. if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, use_keyfile,
  147. SSL_FILETYPE_PEM) <= 0) {
  148. sprintf(msg, "Unable to load private key file %s\n", use_keyfile);
  149. fatal(msg);
  150. }
  151. if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, certfile,
  152. SSL_FILETYPE_PEM) <= 0) {
  153. sprintf(msg, "Unable to load certificate file %s\n", certfile);
  154. fatal(msg);
  155. }
  156. // if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, "DEFAULT") != 1) {
  157. // sprintf(msg, "Unable to set cipher\n");
  158. // fatal(msg);
  159. // }
  160. // Associate socket and ssl object
  161. ctx->ssl = SSL_new(ctx->ssl_ctx);
  162. SSL_set_fd(ctx->ssl, socket);
  163. ret = SSL_accept(ctx->ssl);
  164. if (ret < 0) {
  165. ERR_print_errors_fp(stderr);
  166. return NULL;
  167. }
  168. return ctx;
  169. }
  170. void ws_socket_free(ws_ctx_t *ctx) {
  171. if (ctx->ssl) {
  172. SSL_free(ctx->ssl);
  173. ctx->ssl = NULL;
  174. }
  175. if (ctx->ssl_ctx) {
  176. SSL_CTX_free(ctx->ssl_ctx);
  177. ctx->ssl_ctx = NULL;
  178. }
  179. if (ctx->sockfd) {
  180. shutdown(ctx->sockfd, SHUT_RDWR);
  181. close(ctx->sockfd);
  182. ctx->sockfd = 0;
  183. }
  184. }
  185. /* ------------------------------------------------------- */
  186. int encode_hixie(u_char const *src, size_t srclength,
  187. char *target, size_t targsize) {
  188. int sz = 0, len = 0;
  189. target[sz++] = '\x00';
  190. len = ws_b64_ntop(src, srclength, target+sz, targsize-sz);
  191. if (len < 0) {
  192. return len;
  193. }
  194. sz += len;
  195. target[sz++] = '\xff';
  196. return sz;
  197. }
  198. int decode_hixie(char *src, size_t srclength,
  199. u_char *target, size_t targsize,
  200. unsigned int *opcode, unsigned int *left) {
  201. char *start, *end, cntstr[4];
  202. int i, len, framecount = 0, retlen = 0;
  203. unsigned char chr;
  204. if ((src[0] != '\x00') || (src[srclength-1] != '\xff')) {
  205. handler_emsg("WebSocket framing error\n");
  206. return -1;
  207. }
  208. *left = srclength;
  209. if (srclength == 2 &&
  210. (src[0] == '\xff') &&
  211. (src[1] == '\x00')) {
  212. // client sent orderly close frame
  213. *opcode = 0x8; // Close frame
  214. return 0;
  215. }
  216. *opcode = 0x1; // Text frame
  217. start = src+1; // Skip '\x00' start
  218. do {
  219. /* We may have more than one frame */
  220. end = (char *)memchr(start, '\xff', srclength);
  221. *end = '\x00';
  222. len = ws_b64_pton(start, target+retlen, targsize-retlen);
  223. if (len < 0) {
  224. return len;
  225. }
  226. retlen += len;
  227. start = end + 2; // Skip '\xff' end and '\x00' start
  228. framecount++;
  229. } while (end < (src+srclength-1));
  230. if (framecount > 1) {
  231. snprintf(cntstr, 3, "%d", framecount);
  232. traffic(cntstr);
  233. }
  234. *left = 0;
  235. return retlen;
  236. }
  237. int encode_hybi(u_char const *src, size_t srclength,
  238. char *target, size_t targsize, unsigned int opcode)
  239. {
  240. unsigned long long b64_sz, len_offset = 1, payload_offset = 2;
  241. int len = 0;
  242. if (opcode != OPCODE_TEXT && opcode != OPCODE_BINARY) {
  243. handler_emsg("Invalid opcode. Opcode must be 0x01 for text mode, or 0x02 for binary mode.\n");
  244. return -1;
  245. }
  246. target[0] = (char)((opcode & 0x0F) | 0x80);
  247. if ((int)srclength <= 0) {
  248. return 0;
  249. }
  250. if (opcode & OPCODE_TEXT) {
  251. len = ((srclength - 1) / 3) * 4 + 4;
  252. } else {
  253. len = srclength;
  254. }
  255. if (len <= 125) {
  256. target[1] = (char) len;
  257. payload_offset = 2;
  258. } else if ((len > 125) && (len < 65536)) {
  259. target[1] = (char) 126;
  260. *(u_short*)&(target[2]) = htons(len);
  261. payload_offset = 4;
  262. } else {
  263. handler_emsg("Sending frames larger than 65535 bytes not supported\n");
  264. return -1;
  265. //target[1] = (char) 127;
  266. //*(u_long*)&(target[2]) = htonl(b64_sz);
  267. //payload_offset = 10;
  268. }
  269. if (opcode & OPCODE_TEXT) {
  270. len = ws_b64_ntop(src, srclength, target+payload_offset, targsize-payload_offset);
  271. } else {
  272. memcpy(target+payload_offset, src, srclength);
  273. len = srclength;
  274. }
  275. if (len < 0) {
  276. return len;
  277. }
  278. return len + payload_offset;
  279. }
  280. int decode_hybi(unsigned char *src, size_t srclength,
  281. u_char *target, size_t targsize,
  282. unsigned int *opcode, unsigned int *left)
  283. {
  284. unsigned char *frame, *mask, *payload, save_char;
  285. char cntstr[4];
  286. int masked = 0;
  287. int i = 0, len, framecount = 0;
  288. size_t remaining;
  289. unsigned int target_offset = 0, hdr_length = 0, payload_length = 0;
  290. *left = srclength;
  291. frame = src;
  292. //printf("Deocde new frame\n");
  293. while (1) {
  294. // Need at least two bytes of the header
  295. // Find beginning of next frame. First time hdr_length, masked and
  296. // payload_length are zero
  297. frame += hdr_length + 4*masked + payload_length;
  298. //printf("frame[0..3]: 0x%x 0x%x 0x%x 0x%x (tot: %d)\n",
  299. // (unsigned char) frame[0],
  300. // (unsigned char) frame[1],
  301. // (unsigned char) frame[2],
  302. // (unsigned char) frame[3], srclength);
  303. if (frame > src + srclength) {
  304. //printf("Truncated frame from client, need %d more bytes\n", frame - (src + srclength) );
  305. break;
  306. }
  307. remaining = (src + srclength) - frame;
  308. if (remaining < 2) {
  309. //printf("Truncated frame header from client\n");
  310. break;
  311. }
  312. framecount ++;
  313. *opcode = frame[0] & 0x0f;
  314. masked = (frame[1] & 0x80) >> 7;
  315. if (*opcode == 0x8) {
  316. // client sent orderly close frame
  317. break;
  318. }
  319. payload_length = frame[1] & 0x7f;
  320. if (payload_length < 126) {
  321. hdr_length = 2;
  322. //frame += 2 * sizeof(char);
  323. } else if (payload_length == 126) {
  324. payload_length = (frame[2] << 8) + frame[3];
  325. hdr_length = 4;
  326. } else {
  327. handler_emsg("Receiving frames larger than 65535 bytes not supported\n");
  328. return -1;
  329. }
  330. if ((hdr_length + 4*masked + payload_length) > remaining) {
  331. continue;
  332. }
  333. //printf(" payload_length: %u, raw remaining: %u\n", payload_length, remaining);
  334. payload = frame + hdr_length + 4*masked;
  335. if (*opcode != OPCODE_TEXT && *opcode != OPCODE_BINARY) {
  336. handler_msg("Ignoring non-data frame, opcode 0x%x\n", *opcode);
  337. continue;
  338. }
  339. if (payload_length == 0) {
  340. handler_msg("Ignoring empty frame\n");
  341. continue;
  342. }
  343. if ((payload_length > 0) && (!masked)) {
  344. handler_emsg("Received unmasked payload from client\n");
  345. return -1;
  346. }
  347. // Terminate with a null for base64 decode
  348. save_char = payload[payload_length];
  349. payload[payload_length] = '\0';
  350. // unmask the data
  351. mask = payload - 4;
  352. for (i = 0; i < payload_length; i++) {
  353. payload[i] ^= mask[i%4];
  354. }
  355. if (*opcode & OPCODE_TEXT) {
  356. // base64 decode the data
  357. len = ws_b64_pton((const char*)payload, target+target_offset, targsize);
  358. } else {
  359. memcpy(target+target_offset, payload, payload_length);
  360. len = payload_length;
  361. }
  362. // Restore the first character of the next frame
  363. payload[payload_length] = save_char;
  364. if (len < 0) {
  365. handler_emsg("Base64 decode error code %d", len);
  366. return len;
  367. }
  368. target_offset += len;
  369. //printf(" len %d, raw %s\n", len, frame);
  370. }
  371. if (framecount > 1) {
  372. snprintf(cntstr, 3, "%d", framecount);
  373. traffic(cntstr);
  374. }
  375. *left = remaining;
  376. return target_offset;
  377. }
  378. int parse_handshake(ws_ctx_t *ws_ctx, char *handshake) {
  379. char *start, *end;
  380. headers_t *headers = ws_ctx->headers;
  381. headers->key1[0] = '\0';
  382. headers->key2[0] = '\0';
  383. headers->key3[0] = '\0';
  384. if ((strlen(handshake) < 92) || (bcmp(handshake, "GET ", 4) != 0)) {
  385. return 0;
  386. }
  387. start = handshake+4;
  388. end = strstr(start, " HTTP/1.1");
  389. if (!end) { return 0; }
  390. strncpy(headers->path, start, end-start);
  391. headers->path[end-start] = '\0';
  392. start = strstr(handshake, "\r\nHost: ");
  393. if (!start) { return 0; }
  394. start += 8;
  395. end = strstr(start, "\r\n");
  396. strncpy(headers->host, start, end-start);
  397. headers->host[end-start] = '\0';
  398. headers->origin[0] = '\0';
  399. start = strstr(handshake, "\r\nOrigin: ");
  400. if (start) {
  401. start += 10;
  402. } else {
  403. start = strstr(handshake, "\r\nSec-WebSocket-Origin: ");
  404. if (!start) { return 0; }
  405. start += 24;
  406. }
  407. end = strstr(start, "\r\n");
  408. strncpy(headers->origin, start, end-start);
  409. headers->origin[end-start] = '\0';
  410. start = strstr(handshake, "\r\nSec-WebSocket-Version: ");
  411. if (start) {
  412. // HyBi/RFC 6455
  413. start += 25;
  414. end = strstr(start, "\r\n");
  415. strncpy(headers->version, start, end-start);
  416. headers->version[end-start] = '\0';
  417. ws_ctx->hixie = 0;
  418. ws_ctx->hybi = strtol(headers->version, NULL, 10);
  419. start = strstr(handshake, "\r\nSec-WebSocket-Key: ");
  420. if (!start) { return 0; }
  421. start += 21;
  422. end = strstr(start, "\r\n");
  423. strncpy(headers->key1, start, end-start);
  424. headers->key1[end-start] = '\0';
  425. start = strstr(handshake, "\r\nConnection: ");
  426. if (!start) { return 0; }
  427. start += 14;
  428. end = strstr(start, "\r\n");
  429. strncpy(headers->connection, start, end-start);
  430. headers->connection[end-start] = '\0';
  431. start = strstr(handshake, "\r\nSec-WebSocket-Protocol: ");
  432. if (!start) { return 0; }
  433. start += 26;
  434. end = strstr(start, "\r\n");
  435. strncpy(headers->protocols, start, end-start);
  436. headers->protocols[end-start] = '\0';
  437. } else {
  438. // Hixie 75 or 76
  439. ws_ctx->hybi = 0;
  440. start = strstr(handshake, "\r\n\r\n");
  441. if (!start) { return 0; }
  442. start += 4;
  443. if (strlen(start) == 8) {
  444. ws_ctx->hixie = 76;
  445. strncpy(headers->key3, start, 8);
  446. headers->key3[8] = '\0';
  447. start = strstr(handshake, "\r\nSec-WebSocket-Key1: ");
  448. if (!start) { return 0; }
  449. start += 22;
  450. end = strstr(start, "\r\n");
  451. strncpy(headers->key1, start, end-start);
  452. headers->key1[end-start] = '\0';
  453. start = strstr(handshake, "\r\nSec-WebSocket-Key2: ");
  454. if (!start) { return 0; }
  455. start += 22;
  456. end = strstr(start, "\r\n");
  457. strncpy(headers->key2, start, end-start);
  458. headers->key2[end-start] = '\0';
  459. } else {
  460. ws_ctx->hixie = 75;
  461. }
  462. }
  463. return 1;
  464. }
  465. int parse_hixie76_key(char * key) {
  466. unsigned long i, spaces = 0, num = 0;
  467. for (i=0; i < strlen(key); i++) {
  468. if (key[i] == ' ') {
  469. spaces += 1;
  470. }
  471. if ((key[i] >= 48) && (key[i] <= 57)) {
  472. num = num * 10 + (key[i] - 48);
  473. }
  474. }
  475. return num / spaces;
  476. }
  477. int gen_md5(headers_t *headers, char *target) {
  478. unsigned long key1 = parse_hixie76_key(headers->key1);
  479. unsigned long key2 = parse_hixie76_key(headers->key2);
  480. char *key3 = headers->key3;
  481. MD5_CTX c;
  482. char in[HIXIE_MD5_DIGEST_LENGTH] = {
  483. key1 >> 24, key1 >> 16, key1 >> 8, key1,
  484. key2 >> 24, key2 >> 16, key2 >> 8, key2,
  485. key3[0], key3[1], key3[2], key3[3],
  486. key3[4], key3[5], key3[6], key3[7]
  487. };
  488. MD5_Init(&c);
  489. MD5_Update(&c, (void *)in, sizeof in);
  490. MD5_Final((void *)target, &c);
  491. target[HIXIE_MD5_DIGEST_LENGTH] = '\0';
  492. return 1;
  493. }
  494. static void gen_sha1(headers_t *headers, char *target) {
  495. SHA_CTX c;
  496. unsigned char hash[SHA_DIGEST_LENGTH];
  497. int r;
  498. SHA1_Init(&c);
  499. SHA1_Update(&c, headers->key1, strlen(headers->key1));
  500. SHA1_Update(&c, HYBI_GUID, 36);
  501. SHA1_Final(hash, &c);
  502. r = ws_b64_ntop(hash, sizeof hash, target, HYBI10_ACCEPTHDRLEN);
  503. //assert(r == HYBI10_ACCEPTHDRLEN - 1);
  504. }
  505. ws_ctx_t *do_handshake(int sock) {
  506. char handshake[4096], response[4096], sha1[29], trailer[17];
  507. char *scheme, *pre;
  508. headers_t *headers;
  509. int len, ret, i, offset;
  510. ws_ctx_t * ws_ctx;
  511. char *response_protocol;
  512. // Peek, but don't read the data
  513. len = recv(sock, handshake, 1024, MSG_PEEK);
  514. handshake[len] = 0;
  515. if (len == 0) {
  516. handler_msg("ignoring empty handshake\n");
  517. return NULL;
  518. } else if ((bcmp(handshake, "\x16", 1) == 0) ||
  519. (bcmp(handshake, "\x80", 1) == 0)) {
  520. // SSL
  521. if (!settings.cert) {
  522. handler_msg("SSL connection but no cert specified\n");
  523. return NULL;
  524. } else if (access(settings.cert, R_OK) != 0) {
  525. handler_msg("SSL connection but '%s' not found\n",
  526. settings.cert);
  527. return NULL;
  528. }
  529. ws_ctx = alloc_ws_ctx();
  530. ws_socket_ssl(ws_ctx, sock, settings.cert, settings.key);
  531. if (! ws_ctx) { return NULL; }
  532. scheme = "wss";
  533. handler_msg("using SSL socket\n");
  534. } else if (settings.ssl_only) {
  535. handler_msg("non-SSL connection disallowed\n");
  536. return NULL;
  537. } else {
  538. ws_ctx = alloc_ws_ctx();
  539. ws_socket(ws_ctx, sock);
  540. if (! ws_ctx) { return NULL; }
  541. scheme = "ws";
  542. handler_msg("using plain (not SSL) socket\n");
  543. }
  544. offset = 0;
  545. for (i = 0; i < 10; i++) {
  546. /* (offset + 1): reserve one byte for the trailing '\0' */
  547. if (0 > (len = ws_recv(ws_ctx, handshake + offset, sizeof(handshake) - (offset + 1)))) {
  548. handler_emsg("Read error during handshake: %m\n");
  549. free_ws_ctx(ws_ctx);
  550. return NULL;
  551. } else if (0 == len) {
  552. handler_emsg("Client closed during handshake\n");
  553. free_ws_ctx(ws_ctx);
  554. return NULL;
  555. }
  556. offset += len;
  557. handshake[offset] = 0;
  558. if (strstr(handshake, "\r\n\r\n")) {
  559. break;
  560. } else if (sizeof(handshake) <= (size_t)(offset + 1)) {
  561. handler_emsg("Oversized handshake\n");
  562. free_ws_ctx(ws_ctx);
  563. return NULL;
  564. } else if (9 == i) {
  565. handler_emsg("Incomplete handshake\n");
  566. free_ws_ctx(ws_ctx);
  567. return NULL;
  568. }
  569. usleep(10);
  570. }
  571. //handler_msg("handshake: %s\n", handshake);
  572. if (!parse_handshake(ws_ctx, handshake)) {
  573. handler_emsg("Invalid WS request\n");
  574. free_ws_ctx(ws_ctx);
  575. return NULL;
  576. }
  577. headers = ws_ctx->headers;
  578. if (strstr(headers->protocols, "binary")) {
  579. ws_ctx->opcode = OPCODE_BINARY;
  580. response_protocol = "binary";
  581. } else if (strstr(headers->protocols, "base64")) {
  582. ws_ctx->opcode = OPCODE_TEXT;
  583. response_protocol = "base64";
  584. } else {
  585. handler_emsg("Invalid protocol '%s', expecting 'binary' or 'base64'\n",
  586. headers->protocols);
  587. return NULL;
  588. }
  589. if (ws_ctx->hybi > 0) {
  590. handler_msg("using protocol HyBi/IETF 6455 %d\n", ws_ctx->hybi);
  591. gen_sha1(headers, sha1);
  592. sprintf(response, SERVER_HANDSHAKE_HYBI, sha1, response_protocol);
  593. } else {
  594. if (ws_ctx->hixie == 76) {
  595. handler_msg("using protocol Hixie 76\n");
  596. gen_md5(headers, trailer);
  597. pre = "Sec-";
  598. } else {
  599. handler_msg("using protocol Hixie 75\n");
  600. trailer[0] = '\0';
  601. pre = "";
  602. }
  603. sprintf(response, SERVER_HANDSHAKE_HIXIE, pre, headers->origin, pre, scheme,
  604. headers->host, headers->path, pre, "base64", trailer);
  605. }
  606. //handler_msg("response: %s\n", response);
  607. ws_send(ws_ctx, response, strlen(response));
  608. return ws_ctx;
  609. }
  610. void signal_handler(int sig) {
  611. switch (sig) {
  612. case SIGHUP:
  613. if (settings.whitelist != NULL) {
  614. load_whitelist();
  615. }
  616. break;
  617. case SIGPIPE: pipe_error = 1; break; // handle inline
  618. case SIGTERM:
  619. remove(settings.pid);
  620. exit(0);
  621. break;
  622. }
  623. }
  624. void daemonize(int keepfd) {
  625. int pid, i;
  626. umask(0);
  627. chdir("/");
  628. setgid(getgid());
  629. setuid(getuid());
  630. /* Double fork to daemonize */
  631. pid = fork();
  632. if (pid<0) { fatal("fork error"); }
  633. if (pid>0) { exit(0); } // parent exits
  634. setsid(); // Obtain new process group
  635. pid = fork();
  636. if (pid<0) { fatal("fork error"); }
  637. if (pid>0) {
  638. // parent exits
  639. FILE *pidf = fopen(settings.pid, "w");
  640. if (pidf) {
  641. fprintf(pidf, "%d", pid);
  642. fclose(pidf);
  643. } else {
  644. fprintf(stderr, "Could not write daemon PID file '%s': %s\n", settings.pid, strerror(errno));
  645. }
  646. exit(0);
  647. }
  648. /* Signal handling */
  649. signal(SIGHUP, signal_handler); // catch HUP
  650. signal(SIGTERM, signal_handler); // catch kill
  651. /* Close open files */
  652. for (i=getdtablesize(); i>=0; --i) {
  653. if (i != keepfd) {
  654. close(i);
  655. } else if (settings.verbose) {
  656. printf("keeping fd %d\n", keepfd);
  657. }
  658. }
  659. i=open("/dev/null", O_RDWR); // Redirect stdin
  660. dup(i); // Redirect stdout
  661. dup(i); // Redirect stderr
  662. }
  663. void start_server() {
  664. int lsock, csock, pid, sopt = 1, i;
  665. struct sockaddr_in serv_addr, cli_addr;
  666. socklen_t clilen;
  667. ws_ctx_t *ws_ctx;
  668. /* Initialize buffers */
  669. lsock = socket(AF_INET, SOCK_STREAM, 0);
  670. if (lsock < 0) { error("ERROR creating listener socket"); }
  671. bzero((char *) &serv_addr, sizeof(serv_addr));
  672. serv_addr.sin_family = AF_INET;
  673. serv_addr.sin_port = htons(settings.listen_port);
  674. /* Resolve listen address */
  675. if (settings.listen_host && (settings.listen_host[0] != '\0')) {
  676. if (resolve_host(&serv_addr.sin_addr, settings.listen_host) < -1) {
  677. fatal("Could not resolve listen address");
  678. }
  679. } else {
  680. serv_addr.sin_addr.s_addr = INADDR_ANY;
  681. }
  682. setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (char *)&sopt, sizeof(sopt));
  683. if (bind(lsock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
  684. fatal("ERROR on binding listener socket");
  685. }
  686. listen(lsock,100);
  687. signal(SIGPIPE, signal_handler); // catch pipe
  688. if (settings.daemon) {
  689. daemonize(lsock);
  690. }
  691. // Reep zombies
  692. signal(SIGCHLD, SIG_IGN);
  693. printf("Waiting for connections on %s:%d\n",
  694. settings.listen_host, settings.listen_port);
  695. while (1) {
  696. clilen = sizeof(cli_addr);
  697. pipe_error = 0;
  698. pid = 0;
  699. csock = accept(lsock,
  700. (struct sockaddr *) &cli_addr,
  701. &clilen);
  702. if (csock < 0) {
  703. error("ERROR on accept");
  704. continue;
  705. }
  706. handler_msg("got client connection from %s\n",
  707. inet_ntoa(cli_addr.sin_addr));
  708. if (!settings.run_once) {
  709. handler_msg("forking handler process\n");
  710. pid = fork();
  711. }
  712. if (pid == 0) { // handler process
  713. ws_ctx = do_handshake(csock);
  714. if (settings.run_once) {
  715. if (ws_ctx == NULL) {
  716. // Not a real WebSocket connection
  717. continue;
  718. } else {
  719. // Successful connection, stop listening for new
  720. // connections
  721. close(lsock);
  722. }
  723. }
  724. if (ws_ctx == NULL) {
  725. handler_msg("No connection after handshake\n");
  726. break; // Child process exits
  727. }
  728. settings.handler(ws_ctx);
  729. if (pipe_error) {
  730. handler_emsg("Closing due to SIGPIPE\n");
  731. }
  732. break; // Child process exits
  733. } else { // parent process
  734. settings.handler_id += 1;
  735. }
  736. }
  737. if (pid == 0) {
  738. if (ws_ctx) {
  739. ws_socket_free(ws_ctx);
  740. free_ws_ctx(ws_ctx);
  741. } else {
  742. shutdown(csock, SHUT_RDWR);
  743. close(csock);
  744. }
  745. handler_msg("handler exit\n");
  746. } else {
  747. handler_msg("websockify exit\n");
  748. }
  749. }