flags.c 13 KB

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