flags.c 15 KB

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