1 /* mod-hostserv.c - HostServ module for srvx
2 * Copyright 2012-2013 pk910, Stricted, NurPech
4 * This file is part of srvx.
6 * srvx is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 /* Adds new section to srvx.conf:
26 * "toplevel_access" "600";
27 * "fallback_other_assignment" "1"; //fall back to another assignment when active assignment gets removed
28 * "manager_can_del_toplevel" "0"; //managers of a toplevel group may delete the whole group
29 * "manager_can_del_secondlevel" "0"; //managers of a secondlevel group may delete the whole group
33 * After you started srvx make the bot active:
34 /msg opserv bind hostserv * hostserv.*
35 /msg opserv bind hostserv help *modcmd.help
46 #define KEY_TOPLEVEL "TopLevel"
47 #define KEY_SECONDLEVEL "SecondLevel"
48 #define KEY_MANAGERS "Manager"
49 #define KEY_ASSIGNMENTS "Assignments"
50 #define KEY_ACTIVE "active"
52 static const struct message_entry msgtab[] = {
53 { "HSMSG_ACCESS_DENIED", "Access denied." },
54 { "HSMSG_ASSIGNED_FAKEHOSTS", "Assigned Fakehosts for User $b%s$b:" },
55 { "HSMSG_ASSIGNED_FAKEHOST", " $b%s.%s$b" },
56 { "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE", " $b%s.%s$b (active)" },
57 { "HSMSG_ASSIGNED_FAKEHOST_NOT_ACTIVE", "Fakehost $b%s.%s.$b is not active." },
58 { "HSMSG_ASSIGN_HOWTO", "Use $bset xxx.yyy$b to activate one of the listed fakehosts or $bset *$b to use the default fakehost." },
59 { "HSMSG_ASSIGNED_NONE", " None." },
60 { "HSMSG_MANAGED_FAKEHOSTS", "Fakehosts managed by User $b%s$b:" },
61 { "HSMSG_MANAGED_TOPLEVEL", " $b*.%s$b fakehosts: %d assignments: %d" },
62 { "HSMSG_MANAGED_TOPLEVEL_OWN", " $b*.%s$b fakehosts: %d assignments: %d (active)" },
63 { "HSMSG_MANAGED_FAKEHOST", " $b%s.%s$b assignments: %d" },
64 { "HSMSG_MANAGE_HOWTO", "Use $bview xxx.yyy$b to view more information about a fakehost group." },
65 { "HSMSG_UNKNOWN_FAKEHOST", "Fakehost $b%s.%s$b is unknown or you have no access to manage it." },
66 { "HSMSG_TOPLEVEL_FAKEHOSTS", "Fakehosts in group $b*.%s$b:" },
67 { "HSMSG_TOPLEVEL_FAKEHOST", " $b%s.%s$b assignments: %d managers: %d" },
68 { "HSMSG_TOPLEVEL_INVALID", "The name of the group you entered is invalid ($b%s$b)" },
69 { "HSMSG_MANAGERS_TOPLEVEL", "Managers of group $b*.%s$b:" },
70 { "HSMSG_MANAGERS_FAKEHOST", "Managers of group $b%s.%s$b:" },
71 { "HSMSG_MANAGERS_MANAGERS", " %s" },
72 { "HSMSG_FAKEHOST_ASSIGNMENTS", "Assignments in group $b%s.%s$b:" },
73 { "HSMSG_FAKEHOST_ASSIGNMENT", " $b%s$b (%s.%s.%s)" },
74 { "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE", " $b%s$b (%s.%s.%s) active" },
75 { "HSMSG_FAKEHOST_SET_SUCCESS", "$b%s.%s$b where set successfully." },
76 { "HSMSG_FAKEHOST_TOPLEVEL_ADDED", "Group $b%s$b successfully added." },
77 { "HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", "Group $b%s$b already exists." },
78 { "HSMSG_FAKEHOST_TOPLEVEL_DELETED", "Group $b%s$b successfully deleted." },
79 { "HSMSG_FAKEHOST_SECONDLEVEL_ADDED", "Group $b%s.%s$b successfully added." },
80 { "HSMSG_FAKEHOST_SECONDLEVEL_ALREADY_EXISTS", "Group $b%s.%s$b already exists." },
81 { "HSMSG_FAKEHOST_SECONDLEVEL_DELETED", "Group $b%s.%s$b successfully deleted." },
82 { "HSMSG_MANAGER_ALREADY", "$b%s$b is already a manager of %s.%s" },
83 { "HSMSG_MANAGER_ADDED", "$b%s$b is now a manager of %s.%s" },
84 { "HSMSG_MANAGER_NOT", "$b%s$b is not a manager of %s.%s" },
85 { "HSMSG_MANAGER_DELETED", "$b%s$b is no longer a manager of %s.%s" },
86 { "HSMSG_FAKEHOST_ASSIGN_SUCCESS", "Group $b%s.%s$b was assigned successfully." },
87 { "HSMSG_FAKEHOST_ASSIGNED", "Group $b%s.%s$b is already assigned to the user." },
88 { "HSMSG_FAKEHOST_UNASSIGN_SUCCESS", "Group $b%s.%s$b was unassigned successfully." },
97 int fallback_other_assignment : 1;
98 int manager_can_del_toplevel : 1;
99 int manager_can_del_secondlevel : 1;
102 const char *hostserv_module_deps[] = { NULL };
103 struct userNode *hostserv;
104 struct helpfile *hostserv_helpfile;
105 static struct module *hostserv_module;
106 static struct service *hostserv_service;
107 static struct log_type *HS_LOG;
108 static struct hs_toplevel *toplevels = NULL;
109 static struct hs_user *hostserv_users = NULL;
111 /* FAKEHOST STRUCTS */
114 struct hs_manager *managers;
115 struct hs_secondlevel *secondlevel;
116 struct hs_toplevel *next;
119 struct hs_secondlevel {
120 struct hs_toplevel *toplevel;
122 struct hs_manager *managers;
123 struct hs_assignment *assignments;
124 struct hs_secondlevel *next;
127 struct hs_assignment {
128 struct hs_secondlevel *secondlevel;
129 struct hs_user *user;
131 struct hs_assignment *next;
132 struct hs_assignment *unext; /* for hs_user */
139 struct hs_user *user;
140 struct hs_manager *next;
141 struct hs_manager *unext; /* for hs_user */
145 struct handle_info *hi;
146 struct hs_assignment *assignments;
147 struct hs_manager *managements;
148 struct hs_user *next;
151 /* MANAGEMENT FUNCTIONS for FAKEHOST STRUCTS */
152 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh);
153 static void hs_del_manager(struct hs_manager *manager, int remove_from_object);
154 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh);
155 static void hs_del_user(struct hs_user *user);
157 static void hs_free_all() {
158 struct hs_toplevel *tlfh, *next_tlfh;
159 struct hs_secondlevel *slfh, *next_slfh;
160 struct hs_assignment *assng, *next_assng;
161 struct hs_manager *manager, *next_manager;
162 struct hs_user *user, *next_user;
163 for(tlfh = toplevels; tlfh; tlfh = next_tlfh) {
164 next_tlfh = tlfh->next;
165 for(manager = tlfh->managers; manager; manager = next_manager) {
166 next_manager = manager->next;
169 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
170 next_slfh = slfh->next;
171 for(manager = slfh->managers; manager; manager = next_manager) {
172 next_manager = manager->next;
175 for(assng = slfh->assignments; assng; assng = next_assng) {
176 next_assng = assng->next;
179 free(slfh->fakehost);
182 free(tlfh->fakehost);
185 for(user = hostserv_users; user; user = next_user) {
186 next_user = user->next;
190 hostserv_users = NULL;
193 static struct hs_toplevel *hs_add_toplevel(const char *name) {
194 struct hs_toplevel *tlfh = calloc(1, sizeof(*tlfh));
195 tlfh->fakehost = strdup(name);
196 tlfh->next = toplevels;
201 static void hs_del_toplevel(struct hs_toplevel *tlfh) {
202 //unassign all assignments
203 struct hs_secondlevel *slfh, *next_slfh;
204 struct hs_manager *manager, *next_manager;
205 for(manager = tlfh->managers; manager; manager = next_manager) {
206 next_manager = manager->next;
207 hs_del_manager(manager, 0);
209 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
210 next_slfh = slfh->next;
211 hs_del_secondlevel(slfh, 0);
214 struct hs_toplevel *ctlfh, *last_tlfh = NULL;
215 for(ctlfh = toplevels; ctlfh; ctlfh = ctlfh->next) {
218 last_tlfh->next = ctlfh->next;
220 toplevels = ctlfh->next;
224 free(tlfh->fakehost);
228 static struct hs_secondlevel *hs_add_secondlevel(struct hs_toplevel *tlfh, const char *name) {
229 struct hs_secondlevel *slfh = calloc(1, sizeof(*slfh));
230 slfh->toplevel = tlfh;
231 slfh->fakehost = strdup(name);
232 slfh->next = tlfh->secondlevel;
233 tlfh->secondlevel = slfh;
237 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh) {
238 if(remove_from_tlfh) {
239 struct hs_secondlevel *cslfh, *prev_slfh = NULL;
240 for(cslfh = slfh->toplevel->secondlevel; cslfh; cslfh = cslfh->next) {
243 prev_slfh->next = slfh->next;
245 slfh->toplevel->secondlevel = slfh->next;
251 struct hs_assignment *assng, *next_assng;
252 struct hs_manager *manager, *next_manager;
253 for(manager = slfh->managers; manager; manager = next_manager) {
254 next_manager = manager->next;
255 hs_del_manager(manager, 0);
257 for(assng = slfh->assignments; assng; assng = next_assng) {
258 next_assng = assng->next;
259 hs_del_assignment(assng, 0);
261 free(slfh->fakehost);
265 static struct hs_manager *hs_add_manager_toplevel(struct hs_toplevel *tlfh, struct hs_user *user) {
266 struct hs_manager *manager = calloc(1, sizeof(*manager));
267 manager->user = user;
269 manager->object = tlfh;
270 manager->unext = user->managements;
271 user->managements = manager;
272 manager->next = tlfh->managers;
273 tlfh->managers = manager;
277 static struct hs_manager *hs_add_manager_secondlevel(struct hs_secondlevel *slfh, struct hs_user *user) {
278 struct hs_manager *manager = calloc(1, sizeof(*manager));
279 manager->user = user;
281 manager->object = slfh;
282 manager->unext = user->managements;
283 user->managements = manager;
284 manager->next = slfh->managers;
285 slfh->managers = manager;
289 static void hs_del_manager(struct hs_manager *manager, int remove_from_object) {
290 struct hs_manager *cmanager, *prev_manager = NULL;
291 if(remove_from_object) {
292 if(manager->type == 1) {
293 struct hs_toplevel *tlfh = manager->object;
294 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
295 if(cmanager == manager) {
297 prev_manager->next = manager->next;
299 tlfh->managers = manager->next;
302 prev_manager = cmanager;
304 } else if(manager->type == 2) {
305 struct hs_secondlevel *slfh = manager->object;
306 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
307 if(cmanager == manager) {
309 prev_manager->next = manager->next;
311 slfh->managers = manager->next;
314 prev_manager = cmanager;
319 if(remove_from_object != 2) {
320 for(cmanager = manager->user->managements; cmanager; cmanager = cmanager->unext) {
321 if(cmanager == manager) {
323 prev_manager->unext = manager->unext;
325 manager->user->managements = manager->unext;
328 prev_manager = cmanager;
330 if(manager->user->managements == NULL && manager->user->assignments == NULL)
331 hs_del_user(manager->user);
336 static void hs_activate_assignment(struct hs_user *user, struct hs_assignment *assignment) {
337 struct hs_toplevel *tlfh;
338 struct hs_secondlevel *slfh;
339 struct hs_assignment *assgn;
340 char fakehost[HOSTLEN];
342 assert((!assignment || (assignment->user == user)));
344 if(user->assignments) {
345 for(assgn = user->assignments; assgn; assgn = assgn->unext)
349 if(user->hi->fakehost) {
350 free(user->hi->fakehost);
351 user->hi->fakehost = NULL;
355 slfh = assignment->secondlevel;
356 tlfh = slfh->toplevel;
357 snprintf(fakehost, sizeof(fakehost), "$.%s.%s", slfh->fakehost, tlfh->fakehost);
358 user->hi->fakehost = strdup(fakehost);
359 assignment->active = 1;
362 apply_fakehost(user->hi, NULL);
365 static struct hs_assignment *hs_add_assignment(struct hs_secondlevel *slfh, struct hs_user *user) {
366 struct hs_assignment *assignment = calloc(1, sizeof(*assignment));
367 assignment->secondlevel = slfh;
368 assignment->user = user;
369 if(user->assignments == NULL)
370 assignment->active = 1;
371 assignment->next = slfh->assignments;
372 slfh->assignments = assignment;
373 assignment->unext = user->assignments;
374 user->assignments = assignment;
375 if(assignment->active) {
376 hs_activate_assignment(user, assignment);
381 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh) {
382 struct hs_assignment *cassignment, *prev_assignment = NULL;
383 if(remove_from_slfh) {
384 for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) {
385 if(cassignment == assignment) {
387 prev_assignment->next = assignment->next;
389 assignment->secondlevel->assignments = assignment->next;
392 prev_assignment = cassignment;
394 prev_assignment = NULL;
396 if(remove_from_slfh != 2) {
397 prev_assignment = NULL;
398 for(cassignment = assignment->user->assignments; cassignment; cassignment = cassignment->unext) {
399 if(cassignment == assignment) {
401 prev_assignment->unext = assignment->unext;
403 assignment->user->assignments = assignment->unext;
406 prev_assignment = cassignment;
409 if(assignment->active) {
410 /* use another assignment - or fall back to default user host? */
412 if(hostserv_conf.fallback_other_assignment && assignment->user->assignments) {
413 /* try to find another assignment from same slfh first */
414 for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) {
415 if(cassignment != assignment && cassignment->user == assignment->user)
418 /* use another tlfh assignment */
420 cassignment = assignment->user->assignments;
422 hs_activate_assignment(assignment->user, cassignment);
425 if(assignment->user->managements == NULL && assignment->user->assignments == NULL)
426 hs_del_user(assignment->user);
431 static struct hs_assignment *hs_get_assignment(struct hs_secondlevel *slfh, struct hs_user *user) {
432 struct hs_assignment *cassignment;
433 for(cassignment = slfh->assignments; cassignment; cassignment = cassignment->next) {
434 if(cassignment->user == user)
440 static struct hs_user *hs_get_user(struct handle_info *hi, int create) {
441 struct hs_user *cuser;
442 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
447 cuser = calloc(1, sizeof(*cuser));
449 cuser->next = hostserv_users;
450 hostserv_users = cuser;
456 static void hs_del_user(struct hs_user *user) {
457 if(user->managements) {
458 struct hs_manager *manager, *next_manager;
459 for(manager = user->managements; manager; manager = next_manager) {
460 next_manager = manager->unext;
461 hs_del_manager(manager, 2);
464 if(user->assignments) {
465 struct hs_assignment *assng, *next_assng;
466 for(assng = user->assignments; assng; assng = next_assng) {
467 next_assng = assng->unext;
468 hs_del_assignment(assng, 2);
471 struct hs_user *cuser, *prev_user = NULL;
472 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
475 prev_user->next = user->next;
477 hostserv_users = user->next;
485 /* END OF MANAGEMENT FUNCTIONS */
487 static int check_management_access(struct handle_info *hi, struct hs_toplevel *tlfh, struct hs_secondlevel *slfh) {
490 if(hi->opserv_level >= hostserv_conf.toplevel_access)
492 struct hs_user *user = hs_get_user(hi, 0);
495 struct hs_manager *manager;
497 for(manager = user->managements; manager; manager = manager->next) {
498 if(manager->type == 2 && manager->object == slfh)
503 for(manager = user->managements; manager; manager = manager->next) {
504 if(manager->type == 1 && manager->object == tlfh)
512 static void cmd_view_toplevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_toplevel *tlfh) {
513 reply("HSMSG_TOPLEVEL_FAKEHOSTS", tlfh->fakehost);
514 struct hs_secondlevel *slfh;
515 if(!tlfh->secondlevel)
516 reply("HSMSG_ASSIGNED_NONE");
518 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
519 struct hs_manager *cmanager;
521 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next)
523 struct hs_assignment *assignment;
525 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
527 reply("HSMSG_TOPLEVEL_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments, managers);
529 reply("HSMSG_MANAGERS_TOPLEVEL", tlfh->fakehost);
530 struct hs_manager *cmanager;
532 reply("HSMSG_ASSIGNED_NONE");
534 char managerBuf[351];
536 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
537 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
538 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
541 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
543 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
547 static void cmd_view_secondlevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_secondlevel *slfh) {
548 reply("HSMSG_FAKEHOST_ASSIGNMENTS", slfh->fakehost, slfh->toplevel->fakehost);
549 struct hs_assignment *assignment;
550 for(assignment = slfh->assignments; assignment; assignment = assignment->next) {
551 reply((assignment->active ? "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE" : "HSMSG_FAKEHOST_ASSIGNMENT"), assignment->user->hi->handle, assignment->user->hi->handle, slfh->fakehost, slfh->toplevel->fakehost);
553 reply("HSMSG_MANAGERS_FAKEHOST", slfh->fakehost, slfh->toplevel->fakehost);
554 struct hs_manager *cmanager;
556 reply("HSMSG_ASSIGNED_NONE");
558 char managerBuf[351];
560 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
561 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
562 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
565 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
567 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
571 static MODCMD_FUNC(cmd_view) {
572 struct handle_info *hi;
573 if(argc >= 2 && !strchr(argv[1], '.')) {
574 if (!(hi = modcmd_get_handle_info(user, argv[1])))
576 } else if(argc >= 2) {
577 if (!(hi = user->handle_info)) {
578 reply("NSMSG_MUST_AUTH");
581 char *slfh_name = argv[1];
582 char *tlfh_name = strchr(argv[1], '.');
585 if(strchr(tlfh_name, '.')) {
586 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
589 struct hs_toplevel *tlfh;
590 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
591 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
594 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
597 if(!irccasecmp(slfh_name, "*")) {
598 if(!check_management_access(hi, tlfh, NULL)) {
599 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
602 cmd_view_toplevel_information(user, cmd, tlfh);
605 struct hs_secondlevel *slfh;
606 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
607 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
609 if(!slfh || !check_management_access(hi, tlfh, slfh)) {
610 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
613 cmd_view_secondlevel_information(user, cmd, slfh);
617 if (!(hi = user->handle_info)) {
618 reply("NSMSG_MUST_AUTH");
622 struct hs_user *huser = hs_get_user(hi, 0);
623 reply("HSMSG_ASSIGNED_FAKEHOSTS", hi->handle);
626 struct hs_assignment *assignment;
627 for(assignment = huser->assignments; assignment; assignment = assignment->unext) {
628 reply((assignment->active ? "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE" : "HSMSG_ASSIGNED_FAKEHOST"), assignment->secondlevel->fakehost, assignment->secondlevel->toplevel->fakehost);
631 if(assigncount && huser->hi == user->handle_info)
632 reply("HSMSG_ASSIGN_HOWTO");
635 reply("HSMSG_ASSIGNED_NONE");
636 if(user->handle_info == hi && hi->opserv_level >= hostserv_conf.toplevel_access) {
637 struct hs_toplevel *tlfh;
638 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
639 struct hs_secondlevel *slfh;
640 struct hs_assignment *assignment;
641 int slfhs = 0, assignments = 0;
642 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
644 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
647 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
649 reply("HSMSG_MANAGE_HOWTO");
650 } else if(huser && huser->managements) {
651 reply("HSMSG_MANAGED_FAKEHOSTS", hi->handle);
652 struct hs_manager *manager;
653 for(manager = huser->managements; manager; manager = manager->unext) {
654 if(manager->type == 1) {
655 struct hs_toplevel *tlfh = manager->object;
656 struct hs_secondlevel *slfh;
657 struct hs_assignment *assignment;
658 int slfhs = 0, assignments = 0;
659 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
661 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
664 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
667 for(manager = huser->managements; manager; manager = manager->next) {
668 if(manager->type == 2) {
669 struct hs_secondlevel *slfh = manager->object;
670 struct hs_toplevel *tlfh = slfh->toplevel;
671 //check if the user is already a manager of the tlfh
672 struct hs_manager *cmanager;
673 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
674 if(cmanager->user == huser) break;
676 if(cmanager) continue;
677 struct hs_assignment *assignment;
679 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
681 reply("HSMSG_MANAGED_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments);
684 if(huser->hi == user->handle_info)
685 reply("HSMSG_MANAGE_HOWTO");
690 static MODCMD_FUNC(cmd_addhost) {
691 struct handle_info *hi;
692 struct hs_toplevel *tlfh;
693 struct hs_secondlevel *slfh;
694 if (!(hi = user->handle_info)) {
695 reply("NSMSG_MUST_AUTH");
698 char *slfh_name = argv[1];
699 char *tlfh_name = strchr(argv[1], '.');
701 reply("HSMSG_TOPLEVEL_INVALID", slfh_name);
706 if(strchr(tlfh_name, '.')) {
707 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
710 if(!irccasecmp(slfh_name, "*")) {
711 if(!check_management_access(hi, NULL, NULL)) {
712 reply("HSMSG_ACCESS_DENIED");
715 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
716 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
719 reply("HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", slfh_name, tlfh_name);
722 hs_add_toplevel(tlfh_name);
723 reply("HSMSG_FAKEHOST_TOPLEVEL_ADDED", tlfh_name);
725 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
726 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
729 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
732 if(!check_management_access(hi, tlfh, NULL)) {
733 reply("HSMSG_ACCESS_DENIED");
736 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
737 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
740 reply("HSMSG_FAKEHOST_SECONDLEVEL_ALREADY_EXISTS", slfh_name, tlfh_name);
743 hs_add_secondlevel(tlfh, slfh_name);
744 reply("HSMSG_FAKEHOST_SECONDLEVEL_ADDED", slfh_name, tlfh_name);
749 static MODCMD_FUNC(cmd_delhost) {
750 struct handle_info *hi;
751 if (!(hi = user->handle_info)) {
752 reply("NSMSG_MUST_AUTH");
755 char *slfh_name = argv[1];
756 char *tlfh_name = strchr(argv[1], '.');
759 if(strchr(tlfh_name, '.')) {
760 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
763 struct hs_toplevel *tlfh;
764 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
765 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
768 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
771 if(!irccasecmp(slfh_name, "*")) {
772 if(!check_management_access(hi, (hostserv_conf.manager_can_del_toplevel ? tlfh : NULL), NULL)) { /* manager access is enough to delete whole toplevel? */
773 reply("HSMSG_ACCESS_DENIED");
776 hs_del_toplevel(tlfh);
777 reply("HSMSG_FAKEHOST_TOPLEVEL_DELETED", tlfh_name);
779 struct hs_secondlevel *slfh;
780 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
781 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
784 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
787 if(!check_management_access(hi, tlfh, (hostserv_conf.manager_can_del_secondlevel ? slfh : NULL))) {
788 reply("HSMSG_ACCESS_DENIED");
791 hs_del_secondlevel(slfh, 1);
792 reply("HSMSG_FAKEHOST_SECONDLEVEL_DELETED", slfh_name, tlfh_name);
797 static MODCMD_FUNC(cmd_addmanager) {
798 struct handle_info *hi;
801 if(!strchr(argv[1], '.')) {
802 if (!(hi = modcmd_get_handle_info(user, argv[1])))
806 if (!(hi = modcmd_get_handle_info(user, argv[2])))
810 char *slfh_name = fakehost;
811 char *tlfh_name = strchr(fakehost, '.');
814 if(strchr(tlfh_name, '.')) {
815 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
818 struct hs_toplevel *tlfh;
819 struct hs_secondlevel *slfh = NULL;
820 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
821 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
824 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
827 if(!irccasecmp(slfh_name, "*")) {
828 if(!check_management_access(user->handle_info, tlfh, NULL)) {
829 reply("HSMSG_ACCESS_DENIED");
833 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
834 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
837 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
840 if(!check_management_access(user->handle_info, tlfh, slfh)) {
841 reply("HSMSG_ACCESS_DENIED");
845 struct hs_user *huser = hs_get_user(hi, 1);
846 struct hs_manager *manager;
848 for(manager = huser->managements; manager; manager = manager->next) {
849 if(manager->type == 2 && manager->object == slfh) {
850 reply("HSMSG_MANAGER_ALREADY", hi->handle, slfh_name, tlfh_name);
855 for(manager = huser->managements; manager; manager = manager->next) {
856 if(manager->type == 1 && manager->object == tlfh) {
857 reply("HSMSG_MANAGER_ALREADY", hi->handle, "*", tlfh_name);
862 hs_add_manager_secondlevel(slfh, huser);
864 hs_add_manager_toplevel(tlfh, huser);
865 reply("HSMSG_MANAGER_ADDED", hi->handle, slfh_name, tlfh_name);
871 static MODCMD_FUNC(cmd_delmanager) {
872 struct handle_info *hi;
874 if(!strchr(argv[1], '.')) {
875 if (!(hi = modcmd_get_handle_info(user, argv[1])))
879 if (!(hi = modcmd_get_handle_info(user, argv[2])))
883 char *slfh_name = fakehost;
884 char *tlfh_name = strchr(fakehost, '.');
888 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, "");
892 if(strchr(tlfh_name, '.')) {
893 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
896 struct hs_toplevel *tlfh;
897 struct hs_secondlevel *slfh = NULL;
898 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
899 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
902 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
905 if(!irccasecmp(slfh_name, "*")) {
906 if(!check_management_access(user->handle_info, tlfh, NULL)) {
907 reply("HSMSG_ACCESS_DENIED");
911 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
912 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
915 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
918 if(!check_management_access(user->handle_info, tlfh, slfh)) {
919 reply("HSMSG_ACCESS_DENIED");
923 struct hs_user *huser = hs_get_user(hi, 0);
924 struct hs_manager *manager;
926 reply("HSMSG_MANAGER_NOT", hi->handle, slfh_name, tlfh_name);
930 for(manager = huser->managements; manager; manager = manager->next) {
931 if(manager->type == 2 && manager->object == slfh)
935 reply("HSMSG_MANAGER_NOT", hi->handle, slfh_name, tlfh_name);
939 for(manager = huser->managements; manager; manager = manager->next) {
940 if(manager->type == 1 && manager->object == tlfh)
944 reply("HSMSG_MANAGER_NOT", hi->handle, "*", tlfh_name);
948 hs_del_manager(manager, 1);
949 reply("HSMSG_MANAGER_DELETED", hi->handle, slfh_name, tlfh_name);
953 static MODCMD_FUNC(cmd_set) {
954 struct handle_info *hi;
955 struct hs_user *hs_user;
956 struct hs_assignment *assignment;
957 struct hs_toplevel *tlfh;
958 struct hs_secondlevel *slfh;
961 if (!(hi = user->handle_info)) {
962 reply("NSMSG_MUST_AUTH");
965 hs_user = hs_get_user(hi, 0);
967 return 0; //nothing to do here
968 if(!strcmp(argv[1], "*")) {
969 hs_activate_assignment(hs_user, NULL);
973 char *slfh_name = fakehost;
974 char *tlfh_name = strchr(fakehost, '.');
979 if(!tlfh_name || strchr(tlfh_name, '.')) {
980 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, (tlfh_name ? tlfh_name : ""));
983 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
984 slfh = assignment->secondlevel;
985 tlfh = slfh->toplevel;
986 if(!irccasecmp(tlfh_name, tlfh->fakehost) && !irccasecmp(slfh_name, slfh->fakehost)) {
987 hs_activate_assignment(hs_user, assignment);
988 reply("HSMSG_FAKEHOST_SET_SUCCESS", slfh->fakehost, tlfh->fakehost);
992 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
997 static MODCMD_FUNC(cmd_assign) {
998 struct handle_info *hi;
1000 if(!strchr(argv[1], '.')) {
1001 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1005 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1009 if (!user->handle_info) {
1010 reply("NSMSG_MUST_AUTH");
1013 char *slfh_name = fakehost;
1014 char *tlfh_name = strchr(fakehost, '.');
1018 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, "");
1022 if(strchr(tlfh_name, '.')) {
1023 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1026 struct hs_toplevel *tlfh;
1027 struct hs_secondlevel *slfh;
1028 struct hs_user *hs_user = hs_get_user(hi, 1);
1029 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
1030 if(!irccasecmp(tlfh_name, tlfh->fakehost)) {
1031 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
1032 if(!irccasecmp(slfh_name, slfh->fakehost)) {
1033 if(!check_management_access(user->handle_info, tlfh, slfh)) {
1034 reply("HSMSG_ACCESS_DENIED");
1037 if(hs_get_assignment(slfh, hs_user)) {
1038 reply("HSMSG_FAKEHOST_ASSIGNED", slfh_name, tlfh_name);
1041 hs_add_assignment(slfh, hs_user);
1042 reply("HSMSG_FAKEHOST_ASSIGN_SUCCESS", slfh_name, tlfh_name);
1048 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1052 static MODCMD_FUNC(cmd_unassign) {
1053 struct handle_info *hi;
1055 if(!strchr(argv[1], '.')) {
1056 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1060 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1064 if (!user->handle_info) {
1065 reply("NSMSG_MUST_AUTH");
1068 char *slfh_name = fakehost;
1069 char *tlfh_name = strchr(fakehost, '.');
1073 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, "");
1077 if(strchr(tlfh_name, '.')) {
1078 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1081 struct hs_assignment *assignment;
1082 struct hs_user *hs_user = hs_get_user(hi, 0);
1084 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1087 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
1088 if(!irccasecmp(slfh_name, assignment->secondlevel->fakehost)) {
1089 if(!irccasecmp(tlfh_name, assignment->secondlevel->toplevel->fakehost)) {
1090 if(!check_management_access(user->handle_info, assignment->secondlevel->toplevel, assignment->secondlevel)) {
1091 reply("HSMSG_ACCESS_DENIED");
1094 hs_del_assignment(assignment, 1);
1095 reply("HSMSG_FAKEHOST_UNASSIGN_SUCCESS", slfh_name, tlfh_name);
1100 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1104 static void hostserv_conf_read(void) {
1108 str = "modules/hostserv";
1109 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1110 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1114 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1115 if(hostserv_conf.nick && strcmp(hostserv_conf.nick, str)) {
1118 hostserv_conf.nick = str;
1120 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1121 hostserv_conf.modes = (str ? str : NULL);
1123 str = database_get_data(conf_node, "toplevel_access", RECDB_QSTRING);
1124 unsigned int toplevel_access = atoi(str);
1125 hostserv_conf.toplevel_access = (toplevel_access ? toplevel_access : 600);
1127 str = database_get_data(conf_node, "fallback_other_assignment", RECDB_QSTRING);
1128 hostserv_conf.fallback_other_assignment = (atoi(str) ? 1 : 0);
1130 str = database_get_data(conf_node, "manager_can_del_toplevel", RECDB_QSTRING);
1131 hostserv_conf.manager_can_del_toplevel = (atoi(str) ? 1 : 0);
1133 str = database_get_data(conf_node, "manager_can_del_secondlevel", RECDB_QSTRING);
1134 hostserv_conf.manager_can_del_secondlevel = (atoi(str) ? 1 : 0);
1136 /*str = database_get_data(conf_node, "description", RECDB_QSTRING);
1137 hostserv_conf.description = (str ? str : NULL);*/
1140 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra));
1141 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra));
1143 static int hostserv_saxdb_read_toplevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1144 struct record_data *rd = data;
1145 struct hs_toplevel *tlfh;
1146 struct hs_manager *managerTL;
1147 struct hs_user *user;
1148 struct dict *object;
1150 if (rd->type == RECDB_OBJECT) {
1151 dict_t db = GET_RECORD_OBJECT(rd);
1154 tlfh = hs_add_toplevel(name);
1156 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1157 for (it = dict_first(object); it; it = iter_next(it)) {
1158 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1159 //rd = iter_data(it);
1160 /* nothing in here, yet */
1161 managerTL = hs_add_manager_toplevel(tlfh, user);
1162 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1163 managerTL->active = 1;
1165 managerTL->active = 0;
1169 if ((object = database_get_data(db, KEY_SECONDLEVEL, RECDB_OBJECT)))
1170 dict_foreach(object, hostserv_saxdb_read_secondlevel, tlfh);
1175 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1176 struct record_data *rd = data;
1177 struct hs_toplevel *tlfh = extra;
1178 struct hs_secondlevel *slfh;
1179 struct hs_manager *managerSL;
1180 struct hs_user *user;
1181 struct dict *object;
1183 if (rd->type == RECDB_OBJECT) {
1184 dict_t db = GET_RECORD_OBJECT(rd);
1187 slfh = hs_add_secondlevel(tlfh, name);
1189 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1190 for (it = dict_first(object); it; it = iter_next(it)) {
1191 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1192 //rd = iter_data(it);
1193 /* nothing in here, yet */
1194 managerSL = hs_add_manager_secondlevel(slfh, user);
1195 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1196 managerSL->active = 1;
1198 managerSL->active = 0;
1202 if ((object = database_get_data(db, KEY_ASSIGNMENTS, RECDB_OBJECT)))
1203 dict_foreach(object, hostserv_saxdb_read_assignments, slfh);
1208 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra)) {
1209 struct record_data *rd = data;
1210 struct hs_secondlevel *slfh = extra;
1211 struct hs_user *user;
1212 struct hs_assignment *assng;
1214 if (rd->type == RECDB_OBJECT) {
1215 dict_t db = GET_RECORD_OBJECT(rd);
1217 user = hs_get_user(get_handle_info(name), 1);
1218 assng = hs_add_assignment(slfh, user);
1220 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1230 hostserv_saxdb_read(struct dict *db)
1232 struct dict *object;
1234 if ((object = database_get_data(db, KEY_TOPLEVEL, RECDB_OBJECT)))
1235 dict_foreach(object, hostserv_saxdb_read_toplevel, NULL);
1241 hostserv_saxdb_write(struct saxdb_context *ctx)
1243 struct hs_toplevel *tlfh;
1244 struct hs_secondlevel *slfh;
1245 struct hs_assignment *assng;
1246 struct hs_manager *manager;
1248 saxdb_start_record(ctx, KEY_TOPLEVEL, 1);
1249 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
1250 saxdb_start_record(ctx, tlfh->fakehost, 1);
1252 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1253 for(manager = tlfh->managers; manager; manager = manager->next) {
1254 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1255 //additional manager information?
1257 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1258 saxdb_end_record(ctx);
1260 saxdb_end_record(ctx);
1262 saxdb_start_record(ctx, KEY_SECONDLEVEL, 1);
1263 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
1264 saxdb_start_record(ctx, slfh->fakehost, 1);
1266 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1267 for(manager = slfh->managers; manager; manager = manager->next) {
1268 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1269 //additional manager information?
1271 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1272 saxdb_end_record(ctx);
1274 saxdb_end_record(ctx);
1276 saxdb_start_record(ctx, KEY_ASSIGNMENTS, 1);
1277 for(assng = slfh->assignments; assng; assng = assng->next) {
1278 saxdb_start_record(ctx, assng->user->hi->handle, 0);
1279 //additional assignment information?
1281 saxdb_write_int(ctx, KEY_ACTIVE, assng->active);
1282 saxdb_end_record(ctx);
1284 saxdb_end_record(ctx);
1286 saxdb_end_record(ctx);
1288 saxdb_end_record(ctx);
1290 saxdb_end_record(ctx);
1292 saxdb_end_record(ctx);
1298 static void hostserv_db_cleanup(void) {
1302 int hostserv_init() {
1303 HS_LOG = log_register_type("HostServ", "file:hostserv.log");
1305 const char *nick, *modes;
1306 if((nick = conf_get_data("modules/hostserv/nick", RECDB_QSTRING))) {
1307 modes = conf_get_data("modules/hostserv/modes", RECDB_QSTRING);
1308 hostserv = AddLocalUser(nick, nick, NULL, "Host Service", modes);
1309 hostserv_service = service_register(hostserv);
1310 hostserv_service->trigger = '*';
1313 conf_register_reload(hostserv_conf_read);
1314 reg_exit_func(hostserv_db_cleanup);
1315 saxdb_register("HostServ", hostserv_saxdb_read, hostserv_saxdb_write);
1316 hostserv_module = module_register("HostServ", HS_LOG, "mod-hostserv.help", NULL);
1317 modcmd_register(hostserv_module, "view", cmd_view, 0, MODCMD_REQUIRE_AUTHED, NULL);
1318 modcmd_register(hostserv_module, "addmanager", cmd_addmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1319 modcmd_register(hostserv_module, "delmanager", cmd_delmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1320 modcmd_register(hostserv_module, "set", cmd_set, 2, MODCMD_REQUIRE_AUTHED, NULL);
1321 modcmd_register(hostserv_module, "assign", cmd_assign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1322 modcmd_register(hostserv_module, "unassign", cmd_unassign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1323 modcmd_register(hostserv_module, "addhost", cmd_addhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1324 modcmd_register(hostserv_module, "delhost", cmd_delhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1325 message_register_table(msgtab);
1329 int hostserv_finalize(void) {
1333 str = "modules/hostserv";
1334 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1335 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1339 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1340 if (str) hostserv_conf.nick = str;
1342 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1343 if (str) hostserv_conf.modes = str;