ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/account/chanacs.C
Revision: 1.6
Committed: Sat Sep 22 14:27:30 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +1 -0 lines
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

File Contents

# Content
1 /**
2 * chanacs.C: Channel access lists
3 *
4 * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
5 * Rights to this code are as documented in COPYING.
6 *
7 *
8 * Portions of this file were derived from sources bearing the following license:
9 * Rights to this code are documented in doc/pod/license.pod.
10 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
11 */
12
13 #include "atheme.h"
14 #include <libermyth.h>
15 #include <account/chanacs.h>
16 #include <account/mychan.h>
17 #include <account/myuser.h>
18
19 chanacs_t::callbacks chanacs_t::callback;
20
21 /*****************
22 * C H A N A C S *
23 *****************/
24
25 /* private destructor for chanacs_t */
26 static void
27 chanacs_delete (chanacs_t *ca)
28 {
29 node_t *n;
30
31 return_if_fail (ca != NULL);
32 return_if_fail (ca->mychan != NULL);
33
34 if (!(runflags & RF_STARTING))
35 slog (LG_DEBUG, "chanacs_delete(): %s -> %s", ca->mychan->name, ca->myuser != NULL ? ca->myuser->name : ca->host);
36 n = node_find (ca, &ca->mychan->chanacs);
37 node_del (n, &ca->mychan->chanacs);
38 node_free (n);
39
40 if (ca->myuser != NULL)
41 {
42 n = node_find (ca, &ca->myuser->chanacs);
43 node_del (n, &ca->myuser->chanacs);
44 node_free (n);
45 }
46
47 ca->clear_metadata ();
48
49 delete ca;
50
51 cnt.chanacs--;
52 }
53
54 /*
55 * chanacs_add(mychan_t *mychan, myuser_t *myuser, unsigned int level, time_t ts)
56 *
57 * Creates an access entry mapping between a user and channel.
58 *
59 * Inputs:
60 * - a channel to create a mapping for
61 * - a user to create a mapping for
62 * - a bitmask which describes the access entry's privileges
63 * - a timestamp for this access entry
64 *
65 * Outputs:
66 * - a chanacs_t object which describes the mapping
67 *
68 * Side Effects:
69 * - the channel access list is updated for mychan.
70 */
71 chanacs_t *
72 chanacs_add (mychan_t *mychan, myuser_t *myuser, unsigned int level, time_t ts)
73 {
74 chanacs_t *ca;
75 node_t *n1;
76 node_t *n2;
77
78 return_val_if_fail (mychan != NULL && myuser != NULL, NULL);
79
80 if (*mychan->name != '#')
81 {
82 slog (LG_DEBUG, "chanacs_add(): got non #channel: %s", mychan->name);
83 return NULL;
84 }
85
86 if (!(runflags & RF_STARTING))
87 slog (LG_DEBUG, "chanacs_add(): %s -> %s", mychan->name, myuser->name);
88
89 n1 = node_create ();
90 n2 = node_create ();
91
92 ca = new chanacs_t;
93
94 object_init (asobject (ca), NULL, (destructor_t) chanacs_delete);
95 ca->mychan = mychan;
96 ca->myuser = myuser;
97 ca->level = level & ca_all;
98 ca->ts = ts;
99
100 node_add (ca, n1, &mychan->chanacs);
101 node_add (ca, n2, &myuser->chanacs);
102
103 cnt.chanacs++;
104
105 return ca;
106 }
107
108 /*
109 * chanacs_add_host(mychan_t *mychan, char *host, unsigned int level, time_t ts)
110 *
111 * Creates an access entry mapping between a hostmask and channel.
112 *
113 * Inputs:
114 * - a channel to create a mapping for
115 * - a hostmask to create a mapping for
116 * - a bitmask which describes the access entry's privileges
117 * - a timestamp for this access entry
118 *
119 * Outputs:
120 * - a chanacs_t object which describes the mapping
121 *
122 * Side Effects:
123 * - the channel access list is updated for mychan.
124 */
125 chanacs_t *
126 chanacs_add_host (mychan_t *mychan, char const * const host, unsigned int level, time_t ts)
127 {
128 chanacs_t *ca;
129 node_t *n;
130
131 return_val_if_fail (mychan != NULL && host != NULL, NULL);
132
133 if (*mychan->name != '#')
134 {
135 slog (LG_DEBUG, "chanacs_add_host(): got non #channel: %s", mychan->name);
136 return NULL;
137 }
138
139 if (!(runflags & RF_STARTING))
140 slog (LG_DEBUG, "chanacs_add_host(): %s -> %s", mychan->name, host);
141
142 n = node_create ();
143
144 ca = new chanacs_t;
145
146 object_init (asobject (ca), NULL, (destructor_t) chanacs_delete);
147 ca->mychan = mychan;
148 ca->myuser = NULL;
149 strlcpy (ca->host, host, HOSTLEN);
150 ca->level |= level;
151 ca->ts = ts;
152
153 node_add (ca, n, &mychan->chanacs);
154
155 cnt.chanacs++;
156
157 return ca;
158 }
159
160 chanacs_t *
161 chanacs_find (mychan_t *mychan, myuser_t const * const myuser, unsigned int level)
162 {
163 node_t *n;
164 chanacs_t *ca;
165
166 return_val_if_fail (mychan != NULL && myuser != NULL, NULL);
167
168 LIST_FOREACH (n, mychan->chanacs.head)
169 {
170 ca = static_cast<chanacs_t *> (n->data);
171
172 if (level != 0x0)
173 {
174 if ((ca->myuser == myuser) && ((ca->level & level) == level))
175 return ca;
176 }
177 else if (ca->myuser == myuser)
178 return ca;
179 }
180
181 return NULL;
182 }
183
184 chanacs_t *
185 chanacs_find_host (mychan_t *mychan, char const * const host, unsigned int level)
186 {
187 node_t *n;
188 chanacs_t *ca;
189
190 return_val_if_fail (mychan != NULL && host != NULL, NULL);
191
192 LIST_FOREACH (n, mychan->chanacs.head)
193 {
194 ca = static_cast<chanacs_t *> (n->data);
195
196 if (level != 0x0)
197 {
198 if ((ca->myuser == NULL) && (!match (ca->host, host)) && ((ca->level & level) == level))
199 return ca;
200 }
201 else if ((ca->myuser == NULL) && (!match (ca->host, host)))
202 return ca;
203 }
204
205 return NULL;
206 }
207
208 unsigned int
209 chanacs_host_flags (mychan_t *mychan, char const * const host)
210 {
211 node_t *n;
212 chanacs_t *ca;
213 unsigned int result = 0;
214
215 return_val_if_fail (mychan != NULL && host != NULL, 0);
216
217 LIST_FOREACH (n, mychan->chanacs.head)
218 {
219 ca = (chanacs_t *) n->data;
220
221 if (ca->myuser == NULL && !match (ca->host, host))
222 result |= ca->level;
223 }
224
225 return result;
226 }
227
228 chanacs_t *
229 chanacs_find_host_literal (mychan_t *mychan, char const * const host, unsigned int level)
230 {
231 node_t *n;
232 chanacs_t *ca;
233
234 if ((!mychan) || (!host))
235 return NULL;
236
237 LIST_FOREACH (n, mychan->chanacs.head)
238 {
239 ca = (chanacs_t *) n->data;
240
241 if (level != 0x0)
242 {
243 if ((ca->myuser == NULL) && (!strcasecmp (ca->host, host)) && ((ca->level & level) == level))
244 return ca;
245 }
246 else if ((ca->myuser == NULL) && (!strcasecmp (ca->host, host)))
247 return ca;
248 }
249
250 return NULL;
251 }
252
253 chanacs_t *
254 chanacs_find_host_by_user (mychan_t *mychan, user_t *u, unsigned int level)
255 {
256 node_t *n;
257 chanacs_t *ca;
258
259 return_val_if_fail (mychan != NULL && u != NULL, 0);
260
261 for (n = phandler->next_matching_host_chanacs (mychan, u, mychan->chanacs.head); n != NULL; n = phandler->next_matching_host_chanacs (mychan, u, n->next))
262 {
263 ca = static_cast<chanacs_t *> (n->data);
264 if ((ca->level & level) == level)
265 return ca;
266 }
267
268 return NULL;
269 }
270
271 unsigned int
272 chanacs_host_flags_by_user (mychan_t *mychan, user_t *u)
273 {
274 node_t *n;
275 unsigned int result = 0;
276 chanacs_t *ca;
277
278 return_val_if_fail (mychan != NULL && u != NULL, 0);
279
280 for (n = phandler->next_matching_host_chanacs (mychan, u, mychan->chanacs.head); n != NULL; n = phandler->next_matching_host_chanacs (mychan, u, n->next))
281 {
282 ca = static_cast<chanacs_t *> (n->data);
283 result |= ca->level;
284 }
285
286 return result;
287 }
288
289 chanacs_t *
290 chanacs_find_by_mask (mychan_t *mychan, char const * const mask, unsigned int level)
291 {
292 myuser_t *mu;
293 chanacs_t *ca;
294
295 return_val_if_fail (mychan != NULL && mask != NULL, NULL);
296
297 mu = myuser_t::find (mask);
298
299 if (mu != NULL)
300 {
301 ca = chanacs_find (mychan, mu, level);
302
303 if (ca)
304 return ca;
305 }
306
307 return chanacs_find_host_literal (mychan, mask, level);
308 }
309
310 bool
311 chanacs_user_has_flag (mychan_t *mychan, user_t *u, unsigned int level)
312 {
313 myuser_t *mu;
314
315 return_val_if_fail (mychan != NULL && u != NULL, false);
316
317 mu = u->myuser;
318 if (mu != NULL)
319 {
320 if (chanacs_find (mychan, mu, level))
321 return true;
322 }
323
324 if (chanacs_find_host_by_user (mychan, u, level))
325 return true;
326
327 return false;
328 }
329
330 unsigned int
331 chanacs_user_flags (mychan_t *mychan, user_t *u)
332 {
333 myuser_t *mu;
334 chanacs_t *ca;
335 unsigned int result = 0;
336
337 return_val_if_fail (mychan != NULL && u != NULL, 0);
338
339 mu = u->myuser;
340 if (mu != NULL)
341 {
342 ca = chanacs_find (mychan, mu, 0);
343 if (ca != NULL)
344 result |= ca->level;
345 }
346
347 result |= chanacs_host_flags_by_user (mychan, u);
348
349 return result;
350 }
351
352 bool
353 chanacs_source_has_flag (mychan_t *mychan, sourceinfo_t *si, unsigned int level)
354 {
355 return si->su != NULL ? chanacs_user_has_flag (mychan, si->su, level) : chanacs_find (mychan, si->smu, level) != NULL;
356 }
357
358 unsigned int
359 chanacs_source_flags (mychan_t *mychan, sourceinfo_t *si)
360 {
361 chanacs_t *ca;
362
363 if (si->su != NULL)
364 {
365 return chanacs_user_flags (mychan, si->su);
366 }
367 else
368 {
369 ca = chanacs_find (mychan, si->smu, 0);
370 return ca != NULL ? ca->level : 0;
371 }
372 }
373
374 /* Look for the chanacs exactly matching mu or host (exactly one of mu and
375 * host must be non-NULL). If not found, and create is true, create a new
376 * chanacs with no flags.
377 */
378 chanacs_t *
379 chanacs_open (mychan_t *mychan, myuser_t *mu, char const * const hostmask, bool create)
380 {
381 chanacs_t *ca;
382
383 /* wrt the second assert: only one of mu or hostmask can be not-NULL --nenolod */
384 return_val_if_fail (mychan != NULL, false);
385 return_val_if_fail ((mu != NULL && hostmask == NULL) || (mu == NULL && hostmask != NULL), false);
386
387 if (mu != NULL)
388 {
389 ca = chanacs_find (mychan, mu, 0);
390 if (ca != NULL)
391 return ca;
392 else if (create)
393 return chanacs_add (mychan, mu, 0, NOW);
394 }
395 else
396 {
397 ca = chanacs_find_host_literal (mychan, hostmask, 0);
398 if (ca != NULL)
399 return ca;
400 else if (create)
401 return chanacs_add_host (mychan, hostmask, 0, NOW);
402 }
403 return NULL;
404 }
405
406 /* Destroy a chanacs if it has no flags */
407 void
408 chanacs_close (chanacs_t *ca)
409 {
410 if (ca->level == 0)
411 object_unref (ca);
412 }
413
414 /* Call this with a chanacs_t with level==0 */
415 bool
416 chanacs_is_table_full (chanacs_t *ca)
417 {
418 return chansvs.maxchanacs > 0 && LIST_LENGTH (&ca->mychan->chanacs) > chansvs.maxchanacs;
419 }
420
421 /* Change channel access
422 *
423 * Either mu or hostmask must be specified.
424 * Add the flags in *addflags and remove the flags in *removeflags, updating
425 * these to reflect the actual change. Only allow changes to restrictflags.
426 * Returns true if successful, false if an unallowed change was attempted.
427 * -- jilles */
428 bool
429 chanacs_modify (chanacs_t *ca, unsigned int *addflags, unsigned int *removeflags, unsigned int restrictflags)
430 {
431 return_val_if_fail (ca != NULL, false);
432 return_val_if_fail (addflags != NULL && removeflags != NULL, false);
433
434 *addflags &= ~ca->level;
435 *removeflags &= ca->level & ~*addflags;
436 /* no change? */
437 if ((*addflags | *removeflags) == 0)
438 return true;
439 /* attempting to add bad flag? */
440 if (~restrictflags & *addflags)
441 return false;
442 /* attempting to remove bad flag? */
443 if (~restrictflags & *removeflags)
444 return false;
445 /* attempting to manipulate user with more privs? */
446 if (~restrictflags & ca->level)
447 return false;
448 ca->level = (ca->level | *addflags) & ~*removeflags;
449 ca->ts = NOW;
450
451 return true;
452 }
453
454 /* version that doesn't return the changes made */
455 bool
456 chanacs_modify_simple (chanacs_t *ca, unsigned int addflags, unsigned int removeflags)
457 {
458 unsigned int a, r;
459
460 a = addflags & ca_all;
461 r = removeflags & ca_all;
462 return chanacs_modify (ca, &a, &r, ca_all);
463 }
464
465 /* Change channel access
466 *
467 * Either mu or hostmask must be specified.
468 * Add the flags in *addflags and remove the flags in *removeflags, updating
469 * these to reflect the actual change. Only allow changes to restrictflags.
470 * Returns true if successful, false if an unallowed change was attempted.
471 * -- jilles */
472 bool
473 chanacs_change (mychan_t *mychan, myuser_t *mu, char const * const hostmask, unsigned int *addflags, unsigned int *removeflags, unsigned int restrictflags)
474 {
475 chanacs_t *ca;
476
477 /* wrt the second assert: only one of mu or hostmask can be not-NULL --nenolod */
478 return_val_if_fail (mychan != NULL, false);
479 return_val_if_fail ((mu != NULL && hostmask == NULL) || (mu == NULL && hostmask != NULL), false);
480 return_val_if_fail (addflags != NULL && removeflags != NULL, false);
481
482 if (mu != NULL)
483 {
484 ca = chanacs_find (mychan, mu, 0);
485 if (ca == NULL)
486 {
487 *removeflags = 0;
488 /* no change? */
489 if ((*addflags | *removeflags) == 0)
490 return true;
491 /* attempting to add bad flag? */
492 if (~restrictflags & *addflags)
493 return false;
494 chanacs_add (mychan, mu, *addflags, NOW);
495 }
496 else
497 {
498 *addflags &= ~ca->level;
499 *removeflags &= ca->level & ~*addflags;
500 /* no change? */
501 if ((*addflags | *removeflags) == 0)
502 return true;
503 /* attempting to add bad flag? */
504 if (~restrictflags & *addflags)
505 return false;
506 /* attempting to remove bad flag? */
507 if (~restrictflags & *removeflags)
508 return false;
509 /* attempting to manipulate user with more privs? */
510 if (~restrictflags & ca->level)
511 return false;
512 ca->level = (ca->level | *addflags) & ~*removeflags;
513 ca->ts = NOW;
514 if (ca->level == 0)
515 object_unref (ca);
516 }
517 }
518 else /* hostmask != NULL */
519 {
520 ca = chanacs_find_host_literal (mychan, hostmask, 0);
521 if (ca == NULL)
522 {
523 *removeflags = 0;
524 /* no change? */
525 if ((*addflags | *removeflags) == 0)
526 return true;
527 /* attempting to add bad flag? */
528 if (~restrictflags & *addflags)
529 return false;
530 chanacs_add_host (mychan, hostmask, *addflags, NOW);
531 }
532 else
533 {
534 *addflags &= ~ca->level;
535 *removeflags &= ca->level & ~*addflags;
536 /* no change? */
537 if ((*addflags | *removeflags) == 0)
538 return true;
539 /* attempting to add bad flag? */
540 if (~restrictflags & *addflags)
541 return false;
542 /* attempting to remove bad flag? */
543 if (~restrictflags & *removeflags)
544 return false;
545 /* attempting to manipulate user with more privs? */
546 if (~restrictflags & ca->level)
547 return false;
548 ca->level = (ca->level | *addflags) & ~*removeflags;
549 ca->ts = NOW;
550 if (ca->level == 0)
551 object_unref (ca);
552 }
553 }
554 return true;
555 }
556
557 /* version that doesn't return the changes made */
558 bool
559 chanacs_change_simple (mychan_t *mychan, myuser_t *mu, char const * const hostmask, unsigned int addflags, unsigned int removeflags)
560 {
561 unsigned int a, r;
562
563 a = addflags & ca_all;
564 r = removeflags & ca_all;
565 return chanacs_change (mychan, mu, hostmask, &a, &r, ca_all);
566 }