flags.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. /*
  2. * flags.c -- handles:
  3. * all the flag matching/conversion functions in one neat package :)
  4. *
  5. */
  6. #include "common.h"
  7. #include "crypt.h"
  8. #include "src/mod/share.mod/share.h"
  9. #include "rfc1459.h"
  10. #include "userrec.h"
  11. #include "misc.h"
  12. #include "dccutil.h"
  13. #include "userent.h"
  14. #include "users.h"
  15. static int allow_dk_cmds = 1;
  16. /* Some flags are mutually exclusive -- this roots them out
  17. */
  18. int sanity_check(flag_t atr)
  19. {
  20. /* bots shouldnt have +pmcnaijlys */
  21. if ((atr & USER_BOT) &&
  22. (atr & (USER_PARTY | USER_MASTER | USER_OWNER | USER_ADMIN | USER_HUBA | USER_CHUBA)))
  23. atr &= ~(USER_PARTY | USER_MASTER | USER_OWNER | USER_ADMIN | USER_HUBA | USER_CHUBA);
  24. /* only bots should be there: */
  25. if (!(atr & USER_BOT) &&
  26. (atr & (USER_DOLIMIT | USER_DOVOICE | USER_UPDATEHUB | USER_CHANHUB)))
  27. atr &= ~(USER_DOLIMIT | USER_DOVOICE | USER_UPDATEHUB | USER_CHANHUB);
  28. if ((atr & USER_OP) && (atr & USER_DEOP))
  29. atr &= ~(USER_OP | USER_DEOP);
  30. if ((atr & USER_VOICE) && (atr & USER_QUIET))
  31. atr &= ~(USER_VOICE | USER_QUIET);
  32. /* Can't be admin without also being owner and having hub access */
  33. if (atr & USER_ADMIN)
  34. atr |= USER_OWNER | USER_HUBA | USER_PARTY;
  35. /* Hub access gets chanhub access */
  36. if (atr & USER_HUBA)
  37. atr |= USER_CHUBA;
  38. if (atr & USER_OWNER) {
  39. atr |= USER_MASTER;
  40. }
  41. /* Master implies botmaster, op */
  42. if (atr & USER_MASTER)
  43. atr |= USER_OP | USER_CHUBA;
  44. /* Can't be botnet master without party-line access */
  45. /* if (atr & USER_BOTMAST)
  46. atr |= USER_PARTY;
  47. */
  48. return atr;
  49. }
  50. /* Sanity check on channel attributes
  51. */
  52. int chan_sanity_check(int chatr, int atr)
  53. {
  54. /* admin for chan does shit.. */
  55. if (chatr & USER_ADMIN)
  56. chatr &= ~(USER_ADMIN);
  57. if ((chatr & USER_OP) && (chatr & USER_DEOP))
  58. chatr &= ~(USER_OP | USER_DEOP);
  59. if ((chatr & USER_VOICE) && (chatr & USER_QUIET))
  60. chatr &= ~(USER_VOICE | USER_QUIET);
  61. /* Can't be channel owner without also being channel master */
  62. if (chatr & USER_OWNER)
  63. chatr |= USER_MASTER;
  64. /* Master implies op */
  65. if (chatr & USER_MASTER)
  66. chatr |= USER_OP ;
  67. return chatr;
  68. }
  69. /* Get icon symbol for a user (depending on access level)
  70. *
  71. * (*) owner on any channel
  72. * (+) master on any channel
  73. * (%) botnet master
  74. * (@) op on any channel
  75. * (-) other
  76. */
  77. char geticon(int idx)
  78. {
  79. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0};
  80. if (!dcc[idx].user)
  81. return '-';
  82. get_user_flagrec(dcc[idx].user, &fr, 0);
  83. if (glob_admin(fr))
  84. return '^';
  85. if (chan_owner(fr))
  86. return '*';
  87. if (chan_master(fr))
  88. return '+';
  89. if (chan_op(fr))
  90. return '@';
  91. return '-';
  92. }
  93. void break_down_flags(const char *string, struct flag_record *plus, struct flag_record *minus)
  94. {
  95. struct flag_record *which = plus;
  96. int mode = 0; /* 0 = glob, 1 = chan, 2 = bot */
  97. int flags = plus->match;
  98. if (!(flags & FR_GLOBAL)) {
  99. if (flags & FR_BOT)
  100. mode = 2;
  101. else if (flags & FR_CHAN)
  102. mode = 1;
  103. else
  104. return; /* We dont actually want any..huh? */
  105. }
  106. egg_bzero(plus, sizeof(struct flag_record));
  107. if (minus)
  108. egg_bzero(minus, sizeof(struct flag_record));
  109. plus->match = FR_OR; /* Default binding type OR */
  110. while (*string) {
  111. switch (*string) {
  112. case '+':
  113. which = plus;
  114. break;
  115. case '-':
  116. which = minus ? minus : plus;
  117. break;
  118. case '|':
  119. case '&':
  120. if (!mode) {
  121. if (*string == '|')
  122. plus->match = FR_OR;
  123. else
  124. plus->match = FR_AND;
  125. }
  126. which = plus;
  127. mode++;
  128. if ((mode == 2) && !(flags & (FR_CHAN | FR_BOT)))
  129. string = "";
  130. else if (mode == 3)
  131. mode = 1;
  132. break;
  133. default:
  134. if ((*string >= 'a') && (*string <= 'z')) {
  135. switch (mode) {
  136. case 0:
  137. which->global |= 1 << (*string - 'a');
  138. break;
  139. case 1:
  140. which->chan |= 1 << (*string - 'a');
  141. break;
  142. case 2:
  143. which->bot |= 1 << (*string - 'a');
  144. }
  145. }
  146. /* udef
  147. else if ((*string >= 'A') && (*string <= 'Z')) {
  148. switch (mode) {
  149. case 0:
  150. which->udef_global |= 1 << (*string - 'A');
  151. break;
  152. case 1:
  153. which->udef_chan |= 1 << (*string - 'A');
  154. break;
  155. }
  156. }
  157. else if ((*string >= '0') && (*string <= '9')) {
  158. switch (mode) {
  159. // Map 0->9 to A->K for glob/chan so they are not lost
  160. case 0:
  161. which->udef_global |= 1 << (*string - '0');
  162. break;
  163. case 1:
  164. which->udef_chan |= 1 << (*string - '0');
  165. break;
  166. case 2:
  167. which->bot |= BOT_FLAG0 << (*string - '0');
  168. break;
  169. }
  170. }
  171. */
  172. }
  173. string++;
  174. }
  175. for (which = plus; which; which = (which == plus ? minus : 0)) {
  176. which->global &=USER_VALID;
  177. which->chan &= CHAN_VALID;
  178. which->bot &= BOT_VALID;
  179. }
  180. plus->match |= flags;
  181. if (minus) {
  182. minus->match |= flags;
  183. if (!(plus->match & (FR_AND | FR_OR)))
  184. plus->match |= FR_OR;
  185. }
  186. }
  187. static int flag2str(char *string, flag_t bot)
  188. {
  189. char x = 'a', *old = string;
  190. while (bot && (x <= 'z')) {
  191. if (bot & 1)
  192. *string++ = x;
  193. x++;
  194. bot = bot >> 1;
  195. }
  196. /* udef
  197. x = 'A';
  198. while (udef && (x <= 'Z')) {
  199. if (udef & 1)
  200. *string++ = x;
  201. udef = udef >> 1;
  202. x++;
  203. }
  204. */
  205. if (string == old)
  206. *string++ = '-';
  207. return string - old;
  208. }
  209. static int bot2str(char *string, int bot)
  210. {
  211. char x = 'a', *old = string;
  212. while (x < 'v') {
  213. if (bot & 1)
  214. *string++ = x;
  215. x++;
  216. bot >>= 1;
  217. }
  218. x = '0';
  219. while (x <= '9') {
  220. if (bot & 1)
  221. *string++ = x;
  222. x++;
  223. bot >>= 1;
  224. }
  225. return string - old;
  226. }
  227. int build_flags(char *string, struct flag_record *plus, struct flag_record *minus)
  228. {
  229. char *old = string;
  230. if (plus->match & FR_GLOBAL) {
  231. if (minus && plus->global)
  232. *string++ = '+';
  233. string += flag2str(string, plus->global);
  234. if (minus && minus->global) {
  235. *string++ = '-';
  236. string += flag2str(string, minus->global);
  237. }
  238. } else if (plus->match & FR_BOT) {
  239. if (minus && plus->bot)
  240. *string++ = '+';
  241. string += bot2str(string, plus->bot);
  242. if (minus && minus->bot) {
  243. *string++ = '-';
  244. string += bot2str(string, minus->bot);
  245. }
  246. }
  247. if (plus->match & FR_CHAN) {
  248. if (plus->match & (FR_GLOBAL | FR_BOT))
  249. *string++ = (plus->match & FR_AND) ? '&' : '|';
  250. if (minus && plus->chan)
  251. *string++ = '+';
  252. string += flag2str(string, plus->chan);
  253. if (minus && minus->chan) {
  254. *string++ = '-';
  255. string += flag2str(string, minus->global);
  256. }
  257. }
  258. if ((plus->match & (FR_BOT | FR_CHAN)) == (FR_BOT | FR_CHAN)) {
  259. *string++ = (plus->match & FR_AND) ? '&' : '|';
  260. if (minus && plus->bot)
  261. *string++ = '+';
  262. string += bot2str(string, plus->bot);
  263. if (minus && minus->bot) {
  264. *string++ = '-';
  265. string += bot2str(string, minus->bot);
  266. }
  267. }
  268. if (string == old) {
  269. *string++ = '-';
  270. *string = 0;
  271. return 0;
  272. }
  273. *string = 0;
  274. return string - old;
  275. }
  276. /* Returns 1 if flags match, 0 if they don't. */
  277. int flagrec_ok(struct flag_record *req, struct flag_record *have)
  278. {
  279. if (req->match & FR_AND) {
  280. return flagrec_eq(req, have);
  281. } else if (req->match & FR_OR) {
  282. int hav = have->global;
  283. /* Exception 1 - global +d/+k cant use -|-, unless they are +p */
  284. if (!req->chan && !req->global) {
  285. if (!allow_dk_cmds) {
  286. if (glob_party(*have))
  287. return 1;
  288. if (glob_kick(*have) || chan_kick(*have))
  289. return 0; /* +k cant use -|- commands */
  290. if (glob_deop(*have) || chan_deop(*have))
  291. return 0; /* neither can +d's */
  292. }
  293. return 1;
  294. }
  295. /* The +n/+m checks arent needed anymore since +n/+m
  296. * automatically add lower flags
  297. */
  298. /* if (!1 && ((hav & USER_OP) || (have->chan & USER_OWNER)))
  299. hav |= USER_PARTY;*/
  300. if (hav & req->global)
  301. return 1;
  302. if (have->chan & req->chan)
  303. return 1;
  304. return 0;
  305. }
  306. return 0; /* fr0k3 binding, dont pass it */
  307. }
  308. /* Returns 1 if flags match, 0 if they don't. */
  309. int flagrec_eq(struct flag_record *req, struct flag_record *have)
  310. {
  311. if (req->match & FR_AND) {
  312. if (req->match & FR_GLOBAL) {
  313. if ((req->global &have->global) !=req->global)
  314. return 0;
  315. }
  316. if (req->match & FR_BOT)
  317. if ((req->bot & have->bot) != req->bot)
  318. return 0;
  319. if (req->match & FR_CHAN) {
  320. if ((req->chan & have->chan) != req->chan)
  321. return 0;
  322. }
  323. return 1;
  324. } else if (req->match & FR_OR) {
  325. if (!req->chan && !req->global && !req->bot)
  326. return 1;
  327. if (req->match & FR_GLOBAL) {
  328. if (have->global &req->global)
  329. return 1;
  330. }
  331. if (req->match & FR_BOT)
  332. if (have->bot & req->bot)
  333. return 1;
  334. if (req->match & FR_CHAN) {
  335. if (have->chan & req->chan)
  336. return 1;
  337. }
  338. return 0;
  339. }
  340. return 0; /* fr0k3 binding, dont pass it */
  341. }
  342. void set_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname)
  343. {
  344. struct chanuserrec *cr = NULL;
  345. int oldflags = fr->match;
  346. char buffer[100] = "";
  347. struct chanset_t *ch;
  348. if (!u)
  349. return;
  350. if (oldflags & FR_GLOBAL) {
  351. u->flags = fr->global;
  352. if (!noshare) {
  353. fr->match = FR_GLOBAL;
  354. build_flags(buffer, fr, NULL);
  355. shareout(NULL, "a %s %s\n", u->handle, buffer);
  356. }
  357. }
  358. if ((oldflags & FR_BOT) && (u->flags & USER_BOT))
  359. set_user(&USERENTRY_BOTFL, u, (void *) fr->bot);
  360. /* Don't share bot attrs */
  361. if ((oldflags & FR_CHAN) && chname) {
  362. for (cr = u->chanrec; cr; cr = cr->next)
  363. if (!rfc_casecmp(chname, cr->channel))
  364. break;
  365. ch = findchan_by_dname(chname);
  366. if (!cr && ch) {
  367. cr = calloc(1, sizeof(struct chanuserrec));
  368. cr->next = u->chanrec;
  369. u->chanrec = cr;
  370. strncpyz(cr->channel, chname, sizeof cr->channel);
  371. }
  372. if (cr && ch) {
  373. cr->flags = fr->chan;
  374. if (!noshare) {
  375. fr->match = FR_CHAN;
  376. build_flags(buffer, fr, NULL);
  377. shareout(ch, "a %s %s %s\n", u->handle, buffer, chname);
  378. }
  379. }
  380. }
  381. fr->match = oldflags;
  382. }
  383. /* Always pass the dname (display name) to this function for chname <cybah>
  384. */
  385. void get_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname)
  386. {
  387. struct chanuserrec *cr = NULL;
  388. if (!u) {
  389. fr->global = fr->chan = fr->bot = 0;
  390. return;
  391. }
  392. if (fr->match & FR_GLOBAL) {
  393. fr->global = u->flags;
  394. } else {
  395. fr->global = 0;
  396. }
  397. if (fr->match & FR_BOT) {
  398. fr->bot = (long) get_user(&USERENTRY_BOTFL, u);
  399. } else
  400. fr->bot = 0;
  401. if (fr->match & FR_CHAN) {
  402. if (fr->match & FR_ANYWH) {
  403. fr->chan = u->flags;
  404. for (cr = u->chanrec; cr; cr = cr->next)
  405. if (findchan_by_dname(cr->channel)) {
  406. fr->chan |= cr->flags;
  407. }
  408. } else {
  409. if (chname) {
  410. for (cr = u->chanrec; cr; cr = cr->next) {
  411. if (!rfc_casecmp(chname, cr->channel))
  412. break;
  413. }
  414. }
  415. if (cr) {
  416. fr->chan = cr->flags;
  417. } else {
  418. fr->chan = 0;
  419. }
  420. }
  421. }
  422. }
  423. static int botfl_unpack(struct userrec *u, struct user_entry *e)
  424. {
  425. struct flag_record fr = {FR_BOT, 0, 0, 0};
  426. break_down_flags(e->u.list->extra, &fr, NULL);
  427. list_type_kill(e->u.list);
  428. e->u.ulong = fr.bot;
  429. return 1;
  430. }
  431. static int botfl_pack(struct userrec *u, struct user_entry *e)
  432. {
  433. char x[100] = "";
  434. struct flag_record fr = {FR_BOT, 0, 0, 0};
  435. fr.bot = e->u.ulong;
  436. e->u.list = calloc(1, sizeof(struct list_type));
  437. e->u.list->next = NULL;
  438. e->u.list->extra = calloc(1, build_flags (x, &fr, NULL) + 1);
  439. strcpy(e->u.list->extra, x);
  440. return 1;
  441. }
  442. static int botfl_kill(struct user_entry *e)
  443. {
  444. free(e);
  445. return 1;
  446. }
  447. static int botfl_write_userfile(FILE *f, struct userrec *u, struct user_entry *e)
  448. {
  449. char x[100] = "";
  450. struct flag_record fr = {FR_BOT, 0, 0, 0};
  451. fr.bot = e->u.ulong;
  452. build_flags(x, &fr, NULL);
  453. if (lfprintf(f, "--%s %s\n", e->type->name, x) == EOF)
  454. return 0;
  455. return 1;
  456. }
  457. static int botfl_set(struct userrec *u, struct user_entry *e, void *buf)
  458. {
  459. register long atr = ((long) buf & BOT_VALID);
  460. if (!(u->flags & USER_BOT))
  461. return 1; /* Don't even bother trying to set the
  462. flags for a non-bot */
  463. e->u.ulong = atr;
  464. return 1;
  465. }
  466. static void botfl_display(int idx, struct user_entry *e, struct userrec *u)
  467. {
  468. struct flag_record fr = {FR_BOT, 0, 0, 0};
  469. char x[100] = "";
  470. fr.bot = e->u.ulong;
  471. build_flags(x, &fr, NULL);
  472. dprintf(idx, " BOT FLAGS: %s\n", x);
  473. }
  474. struct user_entry_type USERENTRY_BOTFL =
  475. {
  476. 0, /* always 0 ;) */
  477. 0,
  478. def_dupuser,
  479. botfl_unpack,
  480. botfl_pack,
  481. botfl_write_userfile,
  482. botfl_kill,
  483. def_get,
  484. botfl_set,
  485. botfl_display,
  486. "BOTFL"
  487. };
  488. /* private returns 0 if user has access, and 1 if they dont because of +private
  489. * This function does not check if the user has "op" access, it only checks if the user is
  490. * restricted by +private for the channel
  491. */
  492. int private(struct flag_record fr, struct chanset_t *chan, int type)
  493. {
  494. if (!channel_private(chan) || glob_bot(fr) || glob_owner(fr))
  495. return 0; /* user is implicitly not restricted by +private, they may however be lacking other flags */
  496. if (type == PRIV_OP) {
  497. /* |o implies all flags above. n| has access to all +private. Bots are exempt. */
  498. if (chan_op(fr))
  499. return 0;
  500. } else if (type == PRIV_VOICE) {
  501. if (chan_voice(fr))
  502. return 0;
  503. }
  504. return 1; /* user is restricted by +private */
  505. }
  506. int chk_op(struct flag_record fr, struct chanset_t *chan)
  507. {
  508. if (!chan || (!private(fr, chan, PRIV_OP) && !chk_deop(fr, chan))) {
  509. if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr)))
  510. return 1;
  511. }
  512. return 0;
  513. }
  514. int chk_deop(struct flag_record fr, struct chanset_t *chan)
  515. {
  516. if (chan_deop(fr) || (glob_deop(fr) && !chan_op(fr)))
  517. return 1;
  518. else
  519. return 0;
  520. }
  521. int chk_voice(struct flag_record fr, struct chanset_t *chan)
  522. {
  523. if (!chan || (!private(fr, chan, PRIV_VOICE) && !chk_devoice(fr, chan))) {
  524. if (chan_voice(fr) || (glob_voice(fr) && !chan_quiet(fr)))
  525. return 1;
  526. }
  527. return 0;
  528. }
  529. int chk_devoice(struct flag_record fr, struct chanset_t *chan)
  530. {
  531. if (chan_quiet(fr) || (glob_quiet(fr) && !chan_voice(fr)))
  532. return 1;
  533. else
  534. return 0;
  535. }
  536. int chk_noflood(struct flag_record fr, struct chanset_t *chan)
  537. {
  538. return (chan_noflood(fr) || glob_noflood(fr));
  539. }
  540. int isupdatehub()
  541. {
  542. #ifdef HUB
  543. if (conf.bot->u && (conf.bot->u->flags & USER_UPDATEHUB))
  544. return 1;
  545. else
  546. #endif /* HUB */
  547. return 0;
  548. }
  549. int ischanhub()
  550. {
  551. if (conf.bot->u && (conf.bot->u->flags & USER_CHANHUB))
  552. return 1;
  553. else
  554. return 0;
  555. }
  556. int dovoice(struct chanset_t *chan)
  557. {
  558. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0};
  559. if (!chan) return 0;
  560. get_user_flagrec(conf.bot->u, &fr, chan->dname);
  561. if (glob_dovoice(fr) || chan_dovoice(fr))
  562. return 1;
  563. return 0;
  564. }
  565. int dolimit(struct chanset_t *chan)
  566. {
  567. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0};
  568. if (!chan) return 0;
  569. get_user_flagrec(conf.bot->u, &fr, chan->dname);
  570. if (glob_dolimit(fr) || chan_dolimit(fr))
  571. return 1;
  572. return 0;
  573. }
  574. int whois_access(struct userrec *user, struct userrec *whois_user)
  575. {
  576. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0}, whois = {FR_GLOBAL | FR_CHAN, 0, 0, 0};
  577. get_user_flagrec(user, &fr, NULL);
  578. get_user_flagrec(whois_user, &whois, NULL);
  579. if ((glob_master(whois) && !glob_master(fr)) ||
  580. (glob_owner(whois) && !glob_owner(fr)) ||
  581. (glob_admin(whois) && !glob_admin(fr)) ||
  582. (glob_bot(whois) && !glob_master(fr)))
  583. return 0;
  584. return 1;
  585. }