flags.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  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. #include "chanprog.h"
  16. flag_t FLAG[128];
  17. void
  18. init_flags()
  19. {
  20. unsigned char i;
  21. for (i = 0; i < 'A'; i++)
  22. FLAG[(int) i] = 0;
  23. for (; i <= 'Z'; i++)
  24. FLAG[(int) i] = (flag_t) 1 << (26 + (i - 'A'));
  25. for (; i < 'a'; i++)
  26. FLAG[(int) i] = 0;
  27. for (; i <= 'z'; i++)
  28. FLAG[(int) i] = (flag_t) 1 << (i - 'a');
  29. for (; i < 128; i++)
  30. FLAG[(int) i] = 0;
  31. }
  32. /* Some flags are mutually exclusive -- this roots them out
  33. */
  34. flag_t
  35. sanity_check(flag_t atr, int bot)
  36. {
  37. if (bot && (atr & (USER_PARTY | USER_MASTER | USER_OWNER | USER_ADMIN | USER_HUBA | USER_CHUBA)))
  38. atr &= ~(USER_PARTY | USER_MASTER | USER_OWNER | USER_ADMIN | USER_HUBA | USER_CHUBA);
  39. /* only bots should be there: */
  40. if (!bot && (atr & (USER_DOLIMIT | USER_DOVOICE | USER_UPDATEHUB | USER_CHANHUB)))
  41. atr &= ~(USER_DOLIMIT | USER_DOVOICE | USER_UPDATEHUB | USER_CHANHUB);
  42. if ((atr & USER_OP) && (atr & USER_DEOP))
  43. atr &= ~(USER_OP | USER_DEOP);
  44. if ((atr & USER_AUTOOP) && (atr & USER_DEOP))
  45. atr &= ~(USER_AUTOOP | USER_DEOP);
  46. if ((atr & USER_VOICE) && (atr & USER_QUIET))
  47. atr &= ~(USER_VOICE | USER_QUIET);
  48. /* Can't be admin without also being owner and having hub access */
  49. if (atr & USER_ADMIN)
  50. atr |= USER_OWNER | USER_HUBA | USER_PARTY;
  51. /* Hub access gets chanhub access */
  52. if (atr & USER_HUBA)
  53. atr |= USER_CHUBA;
  54. if (atr & USER_OWNER) {
  55. atr |= USER_MASTER;
  56. }
  57. /* Master implies botmaster, op */
  58. if (atr & USER_MASTER)
  59. atr |= USER_OP;
  60. /* Can't be botnet master without party-line access */
  61. /* if (atr & USER_BOTMAST)
  62. atr |= USER_PARTY;
  63. */
  64. return atr;
  65. }
  66. /* Sanity check on channel attributes
  67. */
  68. flag_t
  69. chan_sanity_check(flag_t chatr)
  70. {
  71. /* admin for chan does shit.. */
  72. if (chatr & USER_ADMIN)
  73. chatr &= ~(USER_ADMIN);
  74. if ((chatr & USER_OP) && (chatr & USER_DEOP))
  75. chatr &= ~(USER_OP | USER_DEOP);
  76. if ((chatr & USER_AUTOOP) && (chatr & USER_DEOP))
  77. chatr &= ~(USER_AUTOOP | USER_DEOP);
  78. if ((chatr & USER_VOICE) && (chatr & USER_QUIET))
  79. chatr &= ~(USER_VOICE | USER_QUIET);
  80. /* Can't be channel owner without also being channel master */
  81. if (chatr & USER_OWNER)
  82. chatr |= USER_MASTER;
  83. /* Master implies op */
  84. if (chatr & USER_MASTER)
  85. chatr |= USER_OP;
  86. return chatr;
  87. }
  88. /* Get icon symbol for a user (depending on access level)
  89. *
  90. * (*) owner on any channel
  91. * (+) master on any channel
  92. * (%) botnet master
  93. * (@) op on any channel
  94. * (-) other
  95. */
  96. char
  97. geticon(int idx)
  98. {
  99. if (!dcc[idx].user)
  100. return '-';
  101. struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0 };
  102. get_user_flagrec(dcc[idx].user, &fr, NULL);
  103. if (glob_admin(fr))
  104. return '^';
  105. if (chan_owner(fr))
  106. return '*';
  107. if (chan_master(fr))
  108. return '+';
  109. if (chan_op(fr))
  110. return '@';
  111. return '-';
  112. }
  113. void
  114. break_down_flags(const char *string, struct flag_record *plus, struct flag_record *minus)
  115. {
  116. struct flag_record *which = plus;
  117. int chan = 0; /* 0 = glob, 1 = chan */
  118. int flags = plus->match;
  119. if (!(flags & FR_GLOBAL)) {
  120. if (flags & FR_CHAN)
  121. chan = 1;
  122. else
  123. return; /* We dont actually want any..huh? */
  124. }
  125. egg_bzero(plus, sizeof(struct flag_record));
  126. if (minus)
  127. egg_bzero(minus, sizeof(struct flag_record));
  128. plus->match = FR_OR; /* Default binding type OR */
  129. while (*string) {
  130. switch (*string) {
  131. case '+':
  132. which = plus;
  133. break;
  134. case '-':
  135. which = minus ? minus : plus;
  136. break;
  137. case '|':
  138. case '&':
  139. if (!chan) {
  140. if (*string == '|')
  141. plus->match = FR_OR;
  142. else
  143. plus->match = FR_AND;
  144. }
  145. which = plus;
  146. chan++;
  147. if (chan == 2)
  148. string = "";
  149. else if (chan == 3)
  150. chan = 1;
  151. break; /* switch() */
  152. default:
  153. {
  154. flag_t flagbit = FLAG[(int) *string];
  155. if (flagbit) {
  156. switch (chan) {
  157. case 0:
  158. /* which->global |= (flag_t) 1 << (*string - 'a'); */
  159. which->global |=flagbit;
  160. break;
  161. case 1:
  162. /* which->chan |= (flag_t) 1 << (*string - 'a'); */
  163. which->chan |= flagbit;
  164. break;
  165. }
  166. }
  167. }
  168. }
  169. string++;
  170. }
  171. /*
  172. * for (which = plus; which; which = (which == plus ? minus : 0)) {
  173. * which->global &= USER_VALID;
  174. * which->chan &= CHAN_VALID;
  175. * }
  176. */
  177. plus->match |= flags;
  178. if (minus) {
  179. minus->match |= flags;
  180. if (!(plus->match & (FR_AND | FR_OR)))
  181. plus->match |= FR_OR;
  182. }
  183. }
  184. static int
  185. flag2str(char *string, flag_t flag)
  186. {
  187. unsigned char c;
  188. char *old = string;
  189. for (c = 0; c < 128; c++)
  190. if (flag & FLAG[(int) c])
  191. *string++ = c;
  192. if (string == old)
  193. *string++ = '-';
  194. return string - old;
  195. }
  196. int
  197. build_flags(char *string, struct flag_record *plus, struct flag_record *minus)
  198. {
  199. char *old = string;
  200. if (plus->match & FR_GLOBAL) {
  201. if (minus && plus->global)
  202. *string++ = '+';
  203. string += flag2str(string, plus->global);
  204. if (minus && minus->global) {
  205. *string++ = '-';
  206. string += flag2str(string, minus->global);
  207. }
  208. }
  209. if (plus->match & FR_CHAN) {
  210. if (plus->match & FR_GLOBAL)
  211. *string++ = (plus->match & FR_AND) ? '&' : '|';
  212. if (minus && plus->chan)
  213. *string++ = '+';
  214. string += flag2str(string, plus->chan);
  215. if (minus && minus->chan) {
  216. *string++ = '-';
  217. string += flag2str(string, minus->global);
  218. }
  219. }
  220. if (string == old) {
  221. *string++ = '-';
  222. *string = 0;
  223. return 0;
  224. }
  225. *string = 0;
  226. return string - old;
  227. }
  228. /* Returns 1 if flags match, 0 if they don't. */
  229. int
  230. flagrec_ok(struct flag_record *req, struct flag_record *have)
  231. {
  232. if (req->match & FR_AND) {
  233. return flagrec_eq(req, have);
  234. } else if (req->match & FR_OR) {
  235. int hav = have->global;
  236. /* no flags, is a match */
  237. if (!req->chan && !req->global)
  238. return 1;
  239. if (hav & req->global)
  240. return 1;
  241. if (have->chan & req->chan)
  242. return 1;
  243. return 0;
  244. }
  245. return 0;
  246. }
  247. /* Returns 1 if flags match, 0 if they don't. */
  248. int
  249. flagrec_eq(struct flag_record *req, struct flag_record *have)
  250. {
  251. if (req->match & FR_AND) {
  252. if (req->match & FR_GLOBAL) {
  253. if ((req->global &have->global) !=req->global)
  254. return 0;
  255. }
  256. if (req->match & FR_CHAN) {
  257. if ((req->chan & have->chan) != req->chan)
  258. return 0;
  259. }
  260. return 1;
  261. } else if (req->match & FR_OR) {
  262. if (!req->chan && !req->global)
  263. return 1;
  264. if (req->match & FR_GLOBAL) {
  265. if (have->global &req->global)
  266. return 1;
  267. }
  268. if (req->match & FR_CHAN) {
  269. if (have->chan & req->chan)
  270. return 1;
  271. }
  272. return 0;
  273. }
  274. return 0; /* fr0k3 binding, dont pass it */
  275. }
  276. void
  277. set_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname)
  278. {
  279. if (!u)
  280. return;
  281. struct chanuserrec *cr = NULL;
  282. flag_t oldflags = fr->match;
  283. char buffer[100] = "";
  284. struct chanset_t *ch;
  285. if (oldflags & FR_GLOBAL) {
  286. u->flags = fr->global;
  287. if (!noshare) {
  288. fr->match = FR_GLOBAL;
  289. build_flags(buffer, fr, NULL);
  290. shareout("a %s %s\n", u->handle, buffer);
  291. }
  292. }
  293. if ((oldflags & FR_CHAN) && chname) {
  294. for (cr = u->chanrec; cr; cr = cr->next)
  295. if (!rfc_casecmp(chname, cr->channel))
  296. break;
  297. ch = findchan_by_dname(chname);
  298. if (!cr && ch) {
  299. cr = (struct chanuserrec *) my_calloc(1, sizeof(struct chanuserrec));
  300. cr->next = u->chanrec;
  301. u->chanrec = cr;
  302. strlcpy(cr->channel, chname, sizeof cr->channel);
  303. }
  304. if (cr && ch) {
  305. cr->flags = fr->chan;
  306. if (!noshare) {
  307. fr->match = FR_CHAN;
  308. build_flags(buffer, fr, NULL);
  309. shareout("a %s %s %s\n", u->handle, buffer, chname);
  310. }
  311. }
  312. }
  313. fr->match = oldflags;
  314. }
  315. /* Always pass the dname (display name) to this function for chname <cybah>
  316. */
  317. void
  318. get_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname)
  319. {
  320. fr->bot = 0;
  321. if (!u) {
  322. fr->global = fr->chan = 0;
  323. return;
  324. }
  325. if (u->bot)
  326. fr->bot = 1;
  327. if (fr->match & FR_GLOBAL) {
  328. fr->global = u->flags;
  329. } else {
  330. fr->global = 0;
  331. }
  332. if (fr->match & FR_CHAN) {
  333. struct chanuserrec *cr = NULL;
  334. if ((fr->match & FR_ANYWH) || (fr->match & FR_ANYCH)) {
  335. if (fr->match & FR_ANYWH)
  336. fr->chan = u->flags;
  337. for (cr = u->chanrec; cr; cr = cr->next) {
  338. if (findchan_by_dname(cr->channel)) {
  339. fr->chan |= cr->flags;
  340. }
  341. }
  342. } else {
  343. if (chname) {
  344. for (cr = u->chanrec; cr; cr = cr->next) {
  345. if (!rfc_casecmp(chname, cr->channel))
  346. break;
  347. }
  348. }
  349. if (cr) {
  350. fr->chan = cr->flags;
  351. } else {
  352. fr->chan = 0;
  353. }
  354. }
  355. }
  356. }
  357. /* private returns 0 if user has access, and 1 if they dont because of +private
  358. * This function does not check if the user has "op" access, it only checks if the user is
  359. * restricted by +private for the channel
  360. */
  361. int
  362. privchan(struct flag_record fr, struct chanset_t *chan, int type)
  363. {
  364. if (!chan || !channel_privchan(chan) || glob_bot(fr) || glob_owner(fr))
  365. return 0; /* user is implicitly not restricted by +private, they may however be lacking other flags */
  366. if (type == PRIV_OP) {
  367. /* |o implies all flags above. n| has access to all +private. Bots are exempt. */
  368. if (chan_op(fr))
  369. return 0;
  370. } else if (type == PRIV_VOICE) {
  371. if (chan_voice(fr) || chan_op(fr))
  372. return 0;
  373. }
  374. return 1; /* user is restricted by +private */
  375. }
  376. int
  377. chk_op(struct flag_record fr, struct chanset_t *chan)
  378. {
  379. return real_chk_op(fr, chan, 1);
  380. }
  381. int
  382. real_chk_op(struct flag_record fr, struct chanset_t *chan, bool botbitch)
  383. {
  384. if (!chan)
  385. return 0;
  386. if (!privchan(fr, chan, PRIV_OP) && !real_chk_deop(fr, chan, botbitch)) {
  387. if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr)))
  388. return 1;
  389. }
  390. return 0;
  391. }
  392. int
  393. chk_autoop(struct flag_record fr, struct chanset_t *chan)
  394. {
  395. if (glob_bot(fr))
  396. return 0;
  397. if (!chan || (!channel_take(chan) && !privchan(fr, chan, PRIV_OP) && chk_op(fr, chan) && !chk_deop(fr, chan))) {
  398. if (channel_autoop(chan) || chan_autoop(fr) || glob_autoop(fr))
  399. return 1;
  400. }
  401. return 0;
  402. }
  403. int chk_deop(struct flag_record fr, struct chanset_t *chan)
  404. {
  405. return real_chk_deop(fr, chan, 1);
  406. }
  407. int
  408. real_chk_deop(struct flag_record fr, struct chanset_t *chan, bool botbitch)
  409. {
  410. if (chan && botbitch && channel_botbitch(chan) && !glob_bot(fr))
  411. return 1;
  412. if (chan_deop(fr) || (glob_deop(fr) && !chan_op(fr)))
  413. return 1;
  414. else
  415. return 0;
  416. }
  417. int
  418. chk_voice(struct flag_record fr, struct chanset_t *chan)
  419. {
  420. if (!chan || (!privchan(fr, chan, PRIV_VOICE) && !chk_devoice(fr))) {
  421. if (chan_voice(fr) || (glob_voice(fr) && !chan_quiet(fr)))
  422. return 1;
  423. }
  424. return 0;
  425. }
  426. int
  427. chk_devoice(struct flag_record fr)
  428. {
  429. if (chan_quiet(fr) || (glob_quiet(fr) && !chan_voice(fr)))
  430. return 1;
  431. else
  432. return 0;
  433. }
  434. int
  435. chk_noflood(struct flag_record fr)
  436. {
  437. return (chan_noflood(fr) || glob_noflood(fr));
  438. }
  439. int
  440. isupdatehub()
  441. {
  442. if (conf.bot->hub && conf.bot->u && (conf.bot->u->flags & USER_UPDATEHUB))
  443. return 1;
  444. else
  445. return 0;
  446. }
  447. int
  448. ischanhub()
  449. {
  450. if (!conf.bot->hub && conf.bot->u && (conf.bot->u->flags & USER_CHANHUB))
  451. return 1;
  452. else
  453. return 0;
  454. }
  455. int
  456. dovoice(struct chanset_t *chan)
  457. {
  458. if (!chan)
  459. return 0;
  460. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  461. get_user_flagrec(conf.bot->u, &fr, chan->dname);
  462. if (glob_dovoice(fr) || chan_dovoice(fr))
  463. return 1;
  464. return 0;
  465. }
  466. int
  467. dolimit(struct chanset_t *chan)
  468. {
  469. if (!chan)
  470. return 0;
  471. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  472. get_user_flagrec(conf.bot->u, &fr, chan->dname);
  473. if (glob_dolimit(fr) || chan_dolimit(fr))
  474. return 1;
  475. return 0;
  476. }
  477. int
  478. whois_access(struct userrec *user, struct userrec *whois_user)
  479. {
  480. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 }, whois = {
  481. FR_GLOBAL | FR_CHAN, 0, 0, 0};
  482. get_user_flagrec(user, &fr, NULL);
  483. get_user_flagrec(whois_user, &whois, NULL);
  484. if (
  485. (isowner(user->handle) && !isowner(user->handle)) ||
  486. (glob_admin(whois) && !glob_admin(fr)) ||
  487. (glob_owner(whois) && !glob_owner(fr)) ||
  488. (glob_master(whois) && !glob_master(fr)) ||
  489. (glob_bot(whois) && !glob_master(fr))
  490. )
  491. return 0;
  492. return 1;
  493. }