server_network.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. // Server network command handlers for HaxServ
  2. //
  3. // Written by: Test_User <hax@andrewyu.org>
  4. //
  5. // This is free and unencumbered software released into the public
  6. // domain.
  7. //
  8. // Anyone is free to copy, modify, publish, use, compile, sell, or
  9. // distribute this software, either in source code form or as a compiled
  10. // binary, for any purpose, commercial or non-commercial, and by any
  11. // means.
  12. //
  13. // In jurisdictions that recognize copyright laws, the author or authors
  14. // of this software dedicate any and all copyright interest in the
  15. // software to the public domain. We make this dedication for the benefit
  16. // of the public at large and to the detriment of our heirs and
  17. // successors. We intend this dedication to be an overt act of
  18. // relinquishment in perpetuity of all present and future rights to this
  19. // software under copyright law.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  24. // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  25. // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  26. // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  27. // OTHER DEALINGS IN THE SOFTWARE.
  28. #include <gnutls/gnutls.h>
  29. #include <netdb.h>
  30. #include <arpa/inet.h>
  31. #include <sys/types.h>
  32. #include <netinet/in.h>
  33. #include <sys/socket.h>
  34. #include <string.h>
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include "network.h"
  38. #include "types.h"
  39. #include "table.h"
  40. #include "tls.h"
  41. #include "config.h"
  42. #include "utils.h"
  43. #include "commands.h"
  44. pthread_mutex_t send_lock = PTHREAD_MUTEX_INITIALIZER;
  45. int resolve(char *address, char *port, struct sockaddr *sockaddr) {
  46. int success;
  47. struct addrinfo hints = {0}, *info;
  48. hints.ai_family = AF_INET;
  49. hints.ai_socktype = SOCK_STREAM;
  50. hints.ai_protocol = IPPROTO_TCP;
  51. hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG;
  52. success = getaddrinfo(address, port, &hints, &info);
  53. if (success == 0) {
  54. *sockaddr = *(info->ai_addr);
  55. freeaddrinfo(info);
  56. }
  57. return success;
  58. }
  59. struct table server_network_commands = {0};
  60. struct table server_list = {0};
  61. struct table user_list = {0};
  62. struct table channel_list = {0};
  63. int ping_handler(struct string sender, uint64_t argc, struct string *argv) {
  64. if (argc < 2) {
  65. puts("Invalid PING recieved! (Missing parameters)");
  66. return 1;
  67. }
  68. uint64_t len = 1 + argv[1].len + 6 + argv[1].len + 1 + sender.len + 1;
  69. char msg[len];
  70. uint64_t offset = 0;
  71. msg[0] = ':';
  72. offset++;
  73. memcpy(msg+offset, argv[1].data, argv[1].len);
  74. offset += argv[1].len;
  75. memcpy(msg+offset, " PONG ", 6);
  76. offset += 6;
  77. memcpy(msg+offset, argv[1].data, argv[1].len);
  78. offset += argv[1].len;
  79. msg[offset] = ' ';
  80. offset++;
  81. memcpy(msg+offset, sender.data, sender.len);
  82. offset += sender.len;
  83. msg[offset] = '\n';
  84. SEND(((struct string){msg, len}));
  85. return 0;
  86. }
  87. int server_handler(struct string sender, uint64_t argc, struct string *argv) {
  88. if (argc < 5) {
  89. puts("Invalid SERVER recieved! (Missing parameters)");
  90. return 1;
  91. }
  92. if (argv[2].len > 20) {
  93. puts("Invalid SERVER recieved! (Distance too large)");
  94. return 1;
  95. }
  96. char err;
  97. uint64_t distance = str_to_unsigned(argv[2], &err);
  98. if (err) {
  99. puts("Invalid SERVER recieved! (Invalid distance given)");
  100. return 1;
  101. }
  102. if (sender.len != 0) {
  103. struct server_info *from = get_table_index(server_list, sender);
  104. if (!from) {
  105. puts("Invalid SERVER recieved! (Unknown source)");
  106. return 1;
  107. }
  108. distance += from->distance + 1;
  109. }
  110. if (get_table_index(server_list, argv[3]) != 0) {
  111. WRITES(2, STRING("Invalid SERVER recieved! (Duplicate SID already connected)\n"));
  112. return 1;
  113. }
  114. struct string address;
  115. address.data = malloc(argv[0].len);
  116. if (address.data == 0)
  117. goto server_handler_oom;
  118. address.len = argv[0].len;
  119. memcpy(address.data, argv[0].data, argv[0].len);
  120. struct string name;
  121. name.data = malloc(argv[4].len);
  122. if (name.data == 0)
  123. goto server_handler_free_address;
  124. name.len = argv[4].len;
  125. memcpy(name.data, argv[4].data, argv[4].len);
  126. struct server_info *server = malloc(sizeof(*server));
  127. if (server == 0)
  128. goto server_handler_free_name;
  129. struct string via;
  130. if (sender.len != 0) { // connected to the sender
  131. via.data = malloc(sender.len);
  132. if (!via.data)
  133. goto server_handler_free_server;
  134. via.len = sender.len;
  135. memcpy(via.data, sender.data, sender.len);
  136. } else { // connected directly to us
  137. via = (struct string){0};
  138. }
  139. *server = (struct server_info){
  140. .name = name,
  141. .address = address,
  142. .distance = distance,
  143. .via = via,
  144. };
  145. if (set_table_index(&server_list, argv[3], server) != 0)
  146. goto server_handler_free_via;
  147. return 0;
  148. server_handler_free_via:
  149. if (sender.len != 0)
  150. free(via.data);
  151. server_handler_free_server:
  152. free(server);
  153. server_handler_free_name:
  154. free(name.data);
  155. server_handler_free_address:
  156. free(address.data);
  157. server_handler_oom:
  158. puts("OOM! (server_handler)");
  159. return 1;
  160. }
  161. int uid_handler(struct string sender, uint64_t argc, struct string *argv) {
  162. if (argc < 10) {
  163. puts("Invalid UID recieved! (Missing parameters)");
  164. return 1;
  165. }
  166. if (argv[1].len > 20 || argv[7].len > 20) {
  167. puts("Invalid UID recieved! (Timestamp too long)");
  168. return 1;
  169. }
  170. if (sender.len == 0) {
  171. puts("Invalid UID recieved! (No source)");
  172. return 1;
  173. }
  174. if (get_table_index(user_list, argv[0])) {
  175. WRITES(2, STRING("Invalid UID revieved! (Attempted to create already-existing user)\n"));
  176. return 1;
  177. }
  178. // TODO: modes
  179. char err;
  180. uint64_t nick_ts = str_to_unsigned(argv[1], &err);
  181. if (err) {
  182. puts("Invalid UID recieved! (Invalid nick timestamp)");
  183. return 1;
  184. }
  185. uint64_t user_ts = str_to_unsigned(argv[7], &err);
  186. if (err) {
  187. puts("Invalid UID recieved! (Invalid user timestamp)");
  188. return 1;
  189. }
  190. struct string server;
  191. server.data = malloc(sender.len);
  192. if (!server.data)
  193. goto uid_handler_oom;
  194. server.len = sender.len;
  195. memcpy(server.data, sender.data, sender.len);
  196. struct string nick;
  197. nick.data = malloc(argv[2].len);
  198. if (!nick.data)
  199. goto uid_handler_free_server;
  200. nick.len = argv[2].len;
  201. memcpy(nick.data, argv[2].data, argv[2].len);
  202. struct string hostname;
  203. hostname.data = malloc(argv[3].len);
  204. if (!hostname.data)
  205. goto uid_handler_free_nick;
  206. hostname.len = argv[3].len;
  207. memcpy(hostname.data, argv[3].data, argv[3].len);
  208. struct string vhost;
  209. vhost.data = malloc(argv[4].len);
  210. if (!vhost.data)
  211. goto uid_handler_free_hostname;
  212. vhost.len = argv[4].len;
  213. memcpy(vhost.data, argv[4].data, argv[4].len);
  214. struct string ident;
  215. ident.data = malloc(argv[5].len);
  216. if (!ident.data)
  217. goto uid_handler_free_vhost;
  218. ident.len = argv[5].len;
  219. memcpy(ident.data, argv[5].data, argv[5].len);
  220. struct string ip;
  221. ip.data = malloc(argv[6].len);
  222. if (!ip.data)
  223. goto uid_handler_free_ident;
  224. ip.len = argv[6].len;
  225. memcpy(ip.data, argv[6].data, argv[6].len);
  226. struct string realname;
  227. realname.data = malloc(argv[argc - 1].len);
  228. if (!realname.data)
  229. goto uid_handler_free_ip;
  230. realname.len = argv[argc - 1].len;
  231. memcpy(realname.data, argv[argc - 1].data, argv[argc - 1].len);
  232. struct user_info *user = malloc(sizeof(*user));
  233. if (!user)
  234. goto uid_handler_free_realname;
  235. *user = (struct user_info){
  236. .nick_ts = nick_ts,
  237. .user_ts = user_ts,
  238. .server = server,
  239. .nick = nick,
  240. .hostname = hostname,
  241. .vhost = vhost,
  242. .ident = ident,
  243. .ip = ip,
  244. .realname = realname,
  245. .opertype = {.data = malloc(0), .len = 0},
  246. .metadata = {.array = malloc(0), .len = 0},
  247. };
  248. if (set_table_index(&user_list, argv[0], user) != 0)
  249. goto uid_handler_free_user;
  250. return 0;
  251. uid_handler_free_user:
  252. free(user);
  253. uid_handler_free_realname:
  254. free(realname.data);
  255. uid_handler_free_ip:
  256. free(ip.data);
  257. uid_handler_free_ident:
  258. free(ident.data);
  259. uid_handler_free_vhost:
  260. free(vhost.data);
  261. uid_handler_free_hostname:
  262. free(hostname.data);
  263. uid_handler_free_nick:
  264. free(nick.data);
  265. uid_handler_free_server:
  266. free(server.data);
  267. uid_handler_oom:
  268. puts("OOM! (uid_handler)");
  269. return 1;
  270. }
  271. int opertype_handler(struct string sender, uint64_t argc, struct string *argv) {
  272. if (argc < 1) {
  273. WRITES(2, STRING("Invalid OPERTYPE recieved! (Missing parameters)\n"));
  274. return 1;
  275. }
  276. if (sender.len == 0) {
  277. WRITES(2, STRING("Invalid OPERTYPE recieved! (No source)\n"));
  278. return 1;
  279. }
  280. struct user_info *user = get_table_index(user_list, sender);
  281. if (!user) {
  282. WRITES(2, STRING("Server "));
  283. WRITES(2, sender);
  284. WRITES(2, STRING(" attempted to set OPERTYPE on a nonexistent user!\n"));
  285. return 1;
  286. }
  287. struct string opertype = {.data = malloc(argv[0].len), .len = argv[0].len};
  288. if (!opertype.data) {
  289. WRITES(2, STRING("OOM! (opertype_handler)\n"));
  290. return 1;
  291. }
  292. memcpy(opertype.data, argv[0].data, argv[0].len);
  293. free(user->opertype.data);
  294. user->opertype = opertype;
  295. return 0;
  296. }
  297. int quit_handler(struct string sender, uint64_t argc, struct string *argv) {
  298. if (argc < 1)
  299. return remove_user(sender, (struct string){0});
  300. else
  301. return remove_user(sender, argv[0]);
  302. }
  303. int kill_handler(struct string sender, uint64_t argc, struct string *argv) {
  304. if (argc < 2) {
  305. WRITES(2, STRING("Invalid KILL recieved! (Missing parameters)\n"));
  306. return 1;
  307. }
  308. // TODO: Get accurate list of what got killed, what to rejoin, etc
  309. struct user_info *user = get_table_index(user_list, argv[0]);
  310. if (!user)
  311. return 0; // TODO: Currently not all local users are considered; fix that, then make this give an error
  312. if (STRING_EQ(user->server, STRING("1HC"))) {
  313. SEND(STRING(":"));
  314. SEND(argv[0]);
  315. SEND(STRING(" QUIT :"));
  316. SEND(argv[1]);
  317. SEND(STRING("\n"));
  318. SEND(STRING("GLOADMODULE m_servprotect\n")); // required for the +k we're about to use
  319. char user_time[21];
  320. snprintf(user_time, 21, "%ld", user->user_ts);
  321. char nick_time[21];
  322. snprintf(nick_time, 21, "%ld", user->nick_ts);
  323. SEND(STRING("UID "));
  324. SEND(argv[0]);
  325. SEND(STRING(" "));
  326. SEND(NULSTR(user_time));
  327. SEND(STRING(" "));
  328. SEND(user->nick);
  329. SEND(STRING(" "));
  330. SEND(user->hostname);
  331. SEND(STRING(" "));
  332. SEND(user->vhost);
  333. SEND(STRING(" "));
  334. SEND(user->ident);
  335. SEND(STRING(" "));
  336. SEND(user->ip);
  337. SEND(STRING(" "));
  338. SEND(NULSTR(nick_time));
  339. SEND(STRING(" +k :"));
  340. SEND(user->realname);
  341. SEND(STRING("\n"));
  342. if (STRING_EQ(argv[0], STRING("1HC000001"))) {
  343. SEND(STRING(":1HC METADATA 1HC000001 ssl_cert :vTrse "));
  344. SEND(client_cert);
  345. SEND(STRING("\n:"));
  346. SEND(argv[0]);
  347. SEND(STRING(" OPERTYPE "));
  348. SEND(opertype);
  349. SEND(STRING("\n"));
  350. }
  351. for (uint64_t i = 0; i < channel_list.len; i++) {
  352. struct channel_info *channel = channel_list.array[i].ptr;
  353. if (has_table_index(channel->user_list, argv[0])) {
  354. char timestamp[21];
  355. SEND(STRING("FJOIN "));
  356. SEND(channel_list.array[i].name);
  357. SEND(STRING(" "));
  358. snprintf(timestamp, 21, "%ld", channel->ts);
  359. SEND(NULSTR(timestamp));
  360. SEND(STRING(" + :,"));
  361. SEND(argv[0]);
  362. SEND(STRING("\n"));
  363. }
  364. }
  365. } else {
  366. return remove_user(argv[0], argv[1]);
  367. }
  368. return 0;
  369. }
  370. int nick_handler(struct string sender, uint64_t argc, struct string *argv) {
  371. if (argc < 2) {
  372. WRITES(2, STRING("Invalid NICK recieved! (Missing parameters)\n"));
  373. return 1;
  374. }
  375. struct user_info *info = get_table_index(user_list, sender);
  376. if (!info) {
  377. WRITES(2, STRING("NICK: Unknown user!\n"));
  378. return 1;
  379. }
  380. for (uint64_t i = 0; i < channel_list.len; i++) { // TODO: More efficient way of doing this
  381. struct channel_info *channel = channel_list.array[i].ptr;
  382. if (has_table_index(channel->user_list, sender) && has_table_index(channel->user_list, STRING("1HC000001"))) {
  383. SENDCLIENT(STRING(":"));
  384. SENDCLIENT(info->nick);
  385. SENDCLIENT(STRING("!"));
  386. SENDCLIENT(info->ident);
  387. SENDCLIENT(STRING("@"));
  388. SENDCLIENT(info->vhost);
  389. SENDCLIENT(STRING(" NICK :"));
  390. SENDCLIENT(argv[0]);
  391. SENDCLIENT(STRING("\r\n"));
  392. break;
  393. }
  394. }
  395. void *tmp = malloc(argv[0].len);
  396. if (!tmp) {
  397. WRITES(2, STRING("OOM! (nick_handler)\n"));
  398. return 1;
  399. }
  400. memcpy(tmp, argv[0].data, argv[0].len);
  401. free(info->nick.data);
  402. info->nick.data = tmp;
  403. info->nick.len = argv[0].len;
  404. if (argv[1].len > 20) {
  405. WRITES(2, STRING("Invalid NICK recieved! (Timestamp too long)\n"));
  406. return 1;
  407. }
  408. char err;
  409. uint64_t ts = str_to_unsigned(argv[1], &err);
  410. if (err) {
  411. WRITES(2, STRING("Invalid NICK recieved! (Invalid timestamp)\n"));
  412. return 1;
  413. }
  414. info->nick_ts = ts;
  415. return 0;
  416. }
  417. int fjoin_handler(struct string sender, uint64_t argc, struct string *argv) {
  418. if (argc < 4) {
  419. WRITES(2, STRING("Invalid FJOIN recieved! (Missing parameters"));
  420. return 1;
  421. }
  422. char err;
  423. uint64_t timestamp = str_to_unsigned(argv[1], &err);
  424. if (err) {
  425. WRITES(2, STRING("Invalid FJOIN recieved! (Invalid timestamp given)\n"));
  426. return 1;
  427. }
  428. // TODO: Parse modes, then make the rest of this work
  429. uint64_t userlist_offset = 3;
  430. {
  431. char dir = '?';
  432. for (uint64_t offset = 0; offset < argv[2].len; offset++) {
  433. if (argv[2].data[offset] == '+') {
  434. dir = '+';
  435. } else if (argv[2].data[offset] == '-') {
  436. dir = '-';
  437. } else if (dir == '?') {
  438. WRITES(2, STRING("Invalid FJOIN recieved! (No direction set for modes)\n"));
  439. return 1;
  440. } else if (channel_mode_types[(unsigned char)argv[2].data[offset]] == MODE_TYPE_UNKNOWN) {
  441. WRITES(2, STRING("Invalid FJOIN recieved! (Unknown mode set on the channel)\n"));
  442. return 1;
  443. } else if (channel_mode_types[(unsigned char)argv[2].data[offset]] != MODE_TYPE_NOARGS && dir == '+') {
  444. userlist_offset++;
  445. }
  446. }
  447. }
  448. if (argc < userlist_offset + 1) {
  449. WRITES(2, STRING("Invalid FJOIN recieved! (Missing mode parameters or user list)\n"));
  450. return 1;
  451. }
  452. struct channel_info *channel = get_table_index(channel_list, argv[0]);
  453. if (!channel) {
  454. channel = malloc(sizeof(*channel));
  455. if (!channel) {
  456. WRITES(2, STRING("OOM! (fjoin_handler)\n"));
  457. return 1;
  458. }
  459. *channel = (struct channel_info){
  460. .ts = timestamp,
  461. .topic = {.data = malloc(0), .len = 0},
  462. .topic_ts = 0,
  463. .modes = {.array = malloc(0), .len = 0},
  464. .user_list = {.array = malloc(0), .len = 0},
  465. .metadata = {.array = malloc(0), .len = 0},
  466. };
  467. set_table_index(&channel_list, argv[0], channel);
  468. }
  469. if (timestamp < channel->ts)
  470. channel->ts = timestamp;
  471. struct string userlist = argv[userlist_offset];
  472. if (userlist.len < 10) // Not enough for any users
  473. return 0;
  474. uint8_t sendclient = has_table_index(channel->user_list, STRING("1HC000001"));
  475. uint64_t offset = 0;
  476. while (1) {
  477. while (offset < userlist.len && userlist.data[offset] != ',')
  478. offset++;
  479. if (offset > (userlist.len - 1) - 9)
  480. break;
  481. offset++;
  482. struct string user = {.data = &(userlist.data[offset]), .len = 9};
  483. struct user_info *user_info = get_table_index(user_list, user);
  484. set_table_index(&(channel->user_list), user, user_info);
  485. if (user_info && sendclient) {
  486. SENDCLIENT(STRING(":"));
  487. SENDCLIENT(user_info->nick);
  488. SENDCLIENT(STRING("!"));
  489. SENDCLIENT(user_info->ident);
  490. SENDCLIENT(STRING("@"));
  491. SENDCLIENT(user_info->vhost);
  492. SENDCLIENT(STRING(" JOIN :"));
  493. SENDCLIENT(argv[0]);
  494. SENDCLIENT(STRING("\r\n"));
  495. }
  496. offset += 10;
  497. }
  498. return 0;
  499. }
  500. int squit_handler(struct string sender, uint64_t argc, struct string *argv) {
  501. if (argc < 1) {
  502. WRITES(2, STRING("Invalid SQUIT recieved! (Missing parameters)\n"));
  503. return 1;
  504. }
  505. struct server_info *server = remove_table_index(&server_list, argv[0]);
  506. if (!server) {
  507. WRITES(2, STRING("Invalid SQUIT received! (Unknown server)\n"));
  508. WRITES(2, STRING("Known servers:\r\n"));
  509. for (uint64_t i = 0; i < server_list.len; i++) {
  510. WRITES(2, server_list.array[i].name);
  511. WRITES(2, STRING("\r\n"));
  512. }
  513. return 1;
  514. }
  515. for (uint64_t i = 0; i < user_list.len;) {
  516. struct user_info *info = user_list.array[i].ptr;
  517. if (STRING_EQ(info->server, argv[0])) {
  518. remove_user(user_list.array[i].name, STRING("*.net *.split"));
  519. } else {
  520. i++; // removal of the user from the table shifts the next user into place for us
  521. }
  522. }
  523. free(server->name.data);
  524. free(server->address.data);
  525. if (server->via.data != 0)
  526. free(server->via.data);
  527. free(server);
  528. return 0;
  529. }
  530. int privmsg_handler(struct string sender, uint64_t argc, struct string *argv) {
  531. if (argc < 2) {
  532. WRITES(2, STRING("Invalid PRIVMSG recieved (Missing parameters)\n"));
  533. return 1;
  534. }
  535. if (sender.len == 0) {
  536. WRITES(2, STRING("Invalid PRIVMSG recieved (No source)\n"));
  537. return 1;
  538. }
  539. struct user_info *user = get_table_index(user_list, sender);
  540. struct server_info *server;
  541. if (user) {
  542. server = 0;
  543. if (argv[0].data[0] == '#') {
  544. struct channel_info *channel = get_table_index(channel_list, argv[0]);
  545. if (channel && has_table_index(channel->user_list, STRING("1HC000001"))) {
  546. SENDCLIENT(STRING(":"));
  547. SENDCLIENT(user->nick);
  548. SENDCLIENT(STRING("!"));
  549. SENDCLIENT(user->ident);
  550. SENDCLIENT(STRING("@"));
  551. SENDCLIENT(user->vhost);
  552. SENDCLIENT(STRING(" PRIVMSG "));
  553. SENDCLIENT(argv[0]);
  554. SENDCLIENT(STRING(" :"));
  555. SENDCLIENT(argv[1]);
  556. SENDCLIENT(STRING("\r\n"));
  557. }
  558. } else if (STRING_EQ(argv[0], STRING("1HC000001"))) {
  559. SENDCLIENT(STRING(":"));
  560. SENDCLIENT(user->nick);
  561. SENDCLIENT(STRING("!"));
  562. SENDCLIENT(user->ident);
  563. SENDCLIENT(STRING("@"));
  564. SENDCLIENT(user->vhost);
  565. SENDCLIENT(STRING(" PRIVMSG "));
  566. SENDCLIENT(client_nick);
  567. SENDCLIENT(STRING(" :"));
  568. SENDCLIENT(argv[1]);
  569. SENDCLIENT(STRING("\r\n"));
  570. }
  571. } else {
  572. server = get_table_index(server_list, sender);
  573. if (server) {
  574. if (argv[0].data[0] == '#') {
  575. struct channel_info *channel = get_table_index(channel_list, argv[0]);
  576. if (channel && has_table_index(channel->user_list, STRING("1HC000001"))) {
  577. SENDCLIENT(STRING(":"));
  578. SENDCLIENT(server->address);
  579. SENDCLIENT(STRING(" PRIVMSG "));
  580. SENDCLIENT(argv[0]);
  581. SENDCLIENT(STRING(" :"));
  582. SENDCLIENT(argv[1]);
  583. SENDCLIENT(STRING("\r\n"));
  584. }
  585. } else if (STRING_EQ(argv[0], STRING("1HC000001"))) {
  586. SENDCLIENT(STRING(":"));
  587. SENDCLIENT(server->address);
  588. SENDCLIENT(STRING(" PRIVMSG "));
  589. SENDCLIENT(client_nick);
  590. SENDCLIENT(STRING(" :"));
  591. SENDCLIENT(argv[1]);
  592. SENDCLIENT(STRING("\r\n"));
  593. }
  594. }
  595. }
  596. uint64_t offset;
  597. if (argv[0].data[0] == '#') {
  598. if (argv[1].len < command_prefix.len || memcmp(argv[1].data, command_prefix.data, command_prefix.len) != 0)
  599. return 0;
  600. struct channel_info *channel_info = get_table_index(channel_list, argv[0]);
  601. if (!channel_info)
  602. return 0;
  603. if (!has_table_index(channel_info->user_list, STRING("1HC000000")))
  604. return 0;
  605. offset = command_prefix.len;
  606. } else if (STRING_EQ(argv[0], STRING("1HC000000"))) {
  607. offset = 0;
  608. } else {
  609. return 0;
  610. }
  611. if (offset >= argv[1].len || argv[1].data[offset] == ' ')
  612. return 0;
  613. uint64_t command_argc = 0;
  614. uint64_t old_offset = offset;
  615. while (offset < argv[1].len) {
  616. while (offset < argv[1].len && argv[1].data[offset] != ' ')
  617. offset++;
  618. command_argc++;
  619. while (offset < argv[1].len && argv[1].data[offset] == ' ')
  620. offset++;
  621. }
  622. offset = old_offset;
  623. struct string command_argv[command_argc]; // argv[0] in this case is the command itself, unlike network command handlers... might change one of these two later to match
  624. uint64_t i = 0;
  625. while (offset < argv[1].len) {
  626. command_argv[i].data = argv[1].data+offset;
  627. uint64_t start = offset;
  628. while (offset < argv[1].len && argv[1].data[offset] != ' ')
  629. offset++;
  630. command_argv[i].len = offset - start;
  631. while (offset < argv[1].len && argv[1].data[offset] == ' ')
  632. offset++;
  633. i++;
  634. }
  635. argv[1].data += old_offset;
  636. argv[1].len -= old_offset;
  637. struct command_def *cmd = get_table_index(user_commands, command_argv[0]);
  638. if (cmd) {
  639. if (!cmd->local_only) {
  640. if (cmd->privs.len != 0 && sender.len != 3) { // servers always count as oper :P
  641. if (!user) {
  642. WRITES(2, STRING("User is unknown!\n"));
  643. SEND(STRING(":1HC000000 NOTICE "));
  644. if (argv[0].data[0] == '#')
  645. SEND(argv[0]);
  646. else
  647. SEND(sender);
  648. SEND(STRING(" :You don't seem to exist... and neither do I!\n"));
  649. return 1; // have already desynced
  650. }
  651. if (user->opertype.len != cmd->privs.len || memcmp(user->opertype.data, cmd->privs.data, cmd->privs.len)) {
  652. // TODO: complain about missing privs
  653. SEND(STRING(":1HC000000 NOTICE "));
  654. if (argv[0].data[0] == '#')
  655. SEND(argv[0]);
  656. else
  657. SEND(sender);
  658. SEND(STRING(" :You are not authorized to execute this command.\n"));
  659. return 0;
  660. }
  661. }
  662. struct string message[] = {
  663. user ? STRING("User ") : (server ? STRING("Server ") : STRING("An unknown user (something desycned... this shouldn't happen)")),
  664. user ? user->nick : (server ? server->address : STRING("")),
  665. STRING(" executes `"),
  666. argv[1],
  667. STRING("'"),
  668. };
  669. privmsg(STRING("1HC000000"), log_channel, sizeof(message)/sizeof(*message), message);
  670. return cmd->func(sender, argv[1], argv[0].data[0] == '#' ? argv[0] : sender, command_argc, command_argv, 0);
  671. } else {
  672. SEND(STRING(":1HC000000 NOTICE "));
  673. if (argv[0].data[0] == '#')
  674. SEND(argv[0]);
  675. else
  676. SEND(sender);
  677. SEND(STRING(" :You are not authorized to execute this command.\n"));
  678. WRITES(1, STRING("Not executing local-only command from a remote source!\n"));
  679. return 0;
  680. }
  681. } else {
  682. SEND(STRING(":1HC000000 NOTICE "));
  683. if (argv[0].data[0] == '#')
  684. SEND(argv[0]);
  685. else
  686. SEND(sender);
  687. SEND(STRING(" :Unknown command: "));
  688. if (argv[0].data[0] == '#')
  689. SEND(command_prefix);
  690. SEND(command_argv[0]);
  691. SEND(STRING("\n"));
  692. return 0;
  693. }
  694. }
  695. int part_handler(struct string sender, uint64_t argc, struct string *argv) {
  696. if (argc < 1) {
  697. WRITES(2, STRING("Invalid PART received! (Missing parameters)\n"));
  698. return 1;
  699. }
  700. struct channel_info *channel = get_table_index(channel_list, argv[0]);
  701. struct user_info *user = get_table_index(user_list, sender);
  702. if (user && channel && has_table_index(channel->user_list, STRING("1HC000001"))) {
  703. SENDCLIENT(STRING(":"));
  704. SENDCLIENT(user->nick);
  705. SENDCLIENT(STRING("!"));
  706. SENDCLIENT(user->ident);
  707. SENDCLIENT(STRING("@"));
  708. SENDCLIENT(user->vhost);
  709. SENDCLIENT(STRING(" PART "));
  710. SENDCLIENT(argv[0]);
  711. if (argc >= 2) {
  712. SENDCLIENT(STRING(" :"));
  713. SENDCLIENT(argv[1]);
  714. }
  715. SENDCLIENT(STRING("\r\n"));
  716. }
  717. if (channel)
  718. remove_table_index(&(channel->user_list), sender);
  719. return 0;
  720. }
  721. int notice_handler(struct string sender, uint64_t argc, struct string *argv) {
  722. if (argc < 2) {
  723. WRITES(2, STRING("Invalid NOTICE received! (Missing parameters)\n"));
  724. return 1;
  725. }
  726. struct user_info *user = get_table_index(user_list, sender);
  727. struct server_info *server;
  728. if (user)
  729. server = 0;
  730. else
  731. server = get_table_index(server_list, sender);
  732. if (!user && !server) {
  733. WRITES(2, STRING("Invalid NOTICE received! (Unknown source)\n"));
  734. return 1;
  735. }
  736. if (argv[0].data[0] == '#') {
  737. struct channel_info *channel = get_table_index(channel_list, argv[0]);
  738. if (channel && has_table_index(channel->user_list, STRING("1HC000001"))) {
  739. SENDCLIENT(STRING(":"));
  740. if (user) {
  741. SENDCLIENT(user->nick);
  742. SENDCLIENT(STRING("!"));
  743. SENDCLIENT(user->ident);
  744. SENDCLIENT(STRING("@"));
  745. SENDCLIENT(user->vhost);
  746. } else {
  747. SENDCLIENT(server->address);
  748. }
  749. SENDCLIENT(STRING(" NOTICE "));
  750. SENDCLIENT(argv[0]);
  751. SENDCLIENT(STRING(" :"));
  752. SENDCLIENT(argv[1]);
  753. SENDCLIENT(STRING("\r\n"));
  754. }
  755. } else if (STRING_EQ(argv[0], STRING("1HC000001"))) {
  756. SENDCLIENT(STRING(":"));
  757. if (user) {
  758. SENDCLIENT(user->nick);
  759. SENDCLIENT(STRING("!"));
  760. SENDCLIENT(user->ident);
  761. SENDCLIENT(STRING("@"));
  762. SENDCLIENT(user->vhost);
  763. } else {
  764. SENDCLIENT(server->address);
  765. }
  766. SENDCLIENT(STRING(" NOTICE "));
  767. SENDCLIENT(argv[0]);
  768. SENDCLIENT(STRING(" :"));
  769. SENDCLIENT(argv[1]);
  770. SENDCLIENT(STRING("\r\n"));
  771. }
  772. return 0;
  773. }
  774. int initservernetwork(void) {
  775. server_network_commands.array = malloc(0);
  776. server_list.array = malloc(0);
  777. user_list.array = malloc(0);
  778. channel_list.array = malloc(0);
  779. set_table_index(&server_network_commands, STRING("PING"), &ping_handler);
  780. set_table_index(&server_network_commands, STRING("SERVER"), &server_handler);
  781. set_table_index(&server_network_commands, STRING("UID"), &uid_handler);
  782. set_table_index(&server_network_commands, STRING("OPERTYPE"), &opertype_handler);
  783. set_table_index(&server_network_commands, STRING("PRIVMSG"), &privmsg_handler);
  784. set_table_index(&server_network_commands, STRING("QUIT"), &quit_handler);
  785. set_table_index(&server_network_commands, STRING("KILL"), &kill_handler);
  786. set_table_index(&server_network_commands, STRING("NICK"), &nick_handler);
  787. set_table_index(&server_network_commands, STRING("FJOIN"), &fjoin_handler);
  788. set_table_index(&server_network_commands, STRING("SQUIT"), &squit_handler);
  789. set_table_index(&server_network_commands, STRING("PART"), &part_handler);
  790. set_table_index(&server_network_commands, STRING("NOTICE"), &notice_handler);
  791. init_user_commands();
  792. int retval = connect_tls();
  793. if (retval != 0) {
  794. printf("connect_tls(): %d\n", retval);
  795. return 1;
  796. }
  797. // probably inefficient to be calling SSL_write this frequently, but also less effort
  798. SEND(STRING("CAPAB START 1202\nCAPAB END\n"));
  799. SEND(STRING("SERVER "));
  800. SEND(server_name);
  801. SEND(STRING(" "));
  802. SEND(send_password);
  803. SEND(STRING(" 0 1HC :HaxServ\n"));
  804. SEND(STRING("BURST "));
  805. time_t current_time = time(NULL);
  806. char current_time_str[21]; // C HaxServ will be deprecated long before we reach 20-digit timestamps
  807. snprintf(current_time_str, 21, "%ld", current_time);
  808. SEND(NULSTR(current_time_str));
  809. SEND(STRING("\n"));
  810. if (add_local_client(STRING("1HC000000"), nick, hostmask, nick, nick, current_time, 0) != 0)
  811. return 1;
  812. struct user_info *user_info = get_table_index(user_list, STRING("1HC000000"));
  813. for (uint64_t i = 0; i < num_prejoin_channels; i++) {
  814. struct channel_info *channel;
  815. channel = malloc(sizeof(*channel));
  816. if (!channel)
  817. return 1;
  818. *channel = (struct channel_info){
  819. .ts = (uint64_t)current_time,
  820. .topic = {.data = malloc(0), .len = 0},
  821. .topic_ts = 0,
  822. .modes = {.array = malloc(0), .len = 0},
  823. .user_list = {.array = malloc(0), .len = 0},
  824. .metadata = {.array = malloc(0), .len = 0},
  825. };
  826. set_table_index(&channel_list, prejoin_channels[i], channel);
  827. set_table_index(&(channel->user_list), STRING("1HC000000"), user_info);
  828. SEND(STRING("FJOIN "));
  829. SEND(prejoin_channels[i]);
  830. SEND(STRING(" "));
  831. SEND(NULSTR(current_time_str));
  832. SEND(STRING(" + :,1HC000000\nMODE "));
  833. SEND(prejoin_channels[i]);
  834. SEND(STRING(" +o 1HC000000\n"));
  835. }
  836. SEND(STRING("ENDBURST\n"));
  837. return 0;
  838. }