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";
30 * After you started srvx make the bot active:
31 /msg opserv bind hostserv * hostserv.*
32 /msg opserv bind hostserv help *modcmd.help
44 #define KEY_TOPLEVEL "TopLevel"
45 #define KEY_SECONDLEVEL "SecondLevel"
46 #define KEY_MANAGERS "Manager"
47 #define KEY_ASSIGNMENTS "Assignments"
48 #define KEY_ACTIVE "active"
50 static const struct message_entry msgtab[] = {
51 { "HSMSG_ACCESS_DENIED", "Access denied." },
52 { "HSMSG_ASSIGNED_FAKEHOSTS", "Assigned Fakehosts for User $b%s$b:" },
53 { "HSMSG_ASSIGNED_FAKEHOST", " $b%s.%s$b" },
54 { "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE", " $b%s.%s$b (active)" },
55 { "HSMSG_ASSIGNED_FAKEHOST_NOT_ACTIVE", "Fakehost $b%s.%s.$b is not active." },
56 { "HSMSG_ASSIGN_HOWTO", "Use $bset xxx.yyy$b to activate one of the listed fakehosts or $bset *$b to use the default fakehost." },
57 { "HSMSG_ASSIGNED_NONE", " None." },
58 { "HSMSG_MANAGED_FAKEHOSTS", "Fakehosts managed by User $b%s$b:" },
59 { "HSMSG_MANAGED_TOPLEVEL", " $b*.%s$b fakehosts: %d assignments: %d" },
60 { "HSMSG_MANAGED_TOPLEVEL_OWN", " $b*.%s$b fakehosts: %d assignments: %d (active)" },
61 { "HSMSG_MANAGED_FAKEHOST", " $b%s.%s$b assignments: %d" },
62 { "HSMSG_MANAGE_HOWTO", "Use $bview xxx.yyy$b to view more information about a fakehost group." },
63 { "HSMSG_UNKNOWN_FAKEHOST", "Fakehost $b%s.%s$b is unknown or you have no access to manage it." },
64 { "HSMSG_TOPLEVEL_FAKEHOSTS", "Fakehosts in group $b*.%s$b:" },
65 { "HSMSG_TOPLEVEL_FAKEHOST", " $b%s.%s$b assignments: %d managers: %d" },
66 { "HSMSG_TOPLEVEL_INVALID", "The name of the group you entered is invalid ($b%s$b)" },
67 { "HSMSG_MANAGERS_TOPLEVEL", "Managers of group $b*.%s$b:" },
68 { "HSMSG_MANAGERS_FAKEHOST", "Managers of group $b%s.%s$b:" },
69 { "HSMSG_MANAGERS_MANAGERS", " %s" },
70 { "HSMSG_FAKEHOST_ASSIGNMENTS", "Assignments in group $b%s.%s$b:" },
71 { "HSMSG_FAKEHOST_ASSIGNMENT", " $b%s$b (%s.%s.%s)" },
72 { "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE", " $b%s$b (%s.%s.%s) active" },
73 { "HSMSG_FAKEHOST_SET_SUCCESS", "$b%s.%s$b where set successfully." },
74 { "HSMSG_FAKEHOST_TOPLEVEL_ADDED", "Group $b%s$b successfully added." },
75 { "HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", "Group $b%s$b already exists." },
76 { "HSMSG_FAKEHOST_TOPLEVEL_DELETED", "Group $b%s$b successfully deleted." },
77 { "HSMSG_FAKEHOST_SECONDLEVEL_ADDED", "Group $b%s.%s$b successfully added." },
78 { "HSMSG_FAKEHOST_SECONDLEVEL_ALREADY_EXISTS", "Group $b%s.%s$b already exists." },
79 { "HSMSG_FAKEHOST_SECONDLEVEL_DELETED", "Group $b%s.%s$b successfully deleted." },
80 { "HSMSG_MANAGER_ALREADY", "$b%s$b is already a manager of %s.%s" },
81 { "HSMSG_MANAGER_ADDED", "$b%s$b is now a manager of %s.%s" },
82 { "HSMSG_MANAGER_NOT", "$b%s$b is not a manager of %s.%s" },
83 { "HSMSG_MANAGER_DELETED", "$b%s$b is no longer a manager of %s.%s" },
84 { "HSMSG_FAKEHOST_ASSIGN_SUCCESS", "Group $b%s.%s$b was assigned successfully." },
85 { "HSMSG_FAKEHOST_UNASSIGN_SUCCESS", "Group $b%s.%s$b was unassigned successfully." },
94 int fallback_other_assignment : 1;
95 int manager_can_del_toplevel : 1;
96 int manager_can_del_secondlevel : 1;
99 const char *hostserv_module_deps[] = { NULL };
100 struct userNode *hostserv;
101 struct helpfile *hostserv_helpfile;
102 static struct module *hostserv_module;
103 static struct service *hostserv_service;
104 static struct log_type *HS_LOG;
105 static struct hs_toplevel *toplevels = NULL;
106 static struct hs_user *hostserv_users = NULL;
108 /* FAKEHOST STRUCTS */
111 struct hs_manager *managers;
112 struct hs_secondlevel *secondlevel;
113 struct hs_toplevel *next;
116 struct hs_secondlevel {
117 struct hs_toplevel *toplevel;
119 struct hs_manager *managers;
120 struct hs_assignment *assignments;
121 struct hs_secondlevel *next;
124 struct hs_assignment {
125 struct hs_secondlevel *secondlevel;
126 struct hs_user *user;
128 struct hs_assignment *next;
129 struct hs_assignment *unext; /* for hs_user */
136 struct hs_user *user;
137 struct hs_manager *next;
138 struct hs_manager *unext; /* for hs_user */
142 struct handle_info *hi;
143 struct hs_assignment *assignments;
144 struct hs_manager *managements;
145 struct hs_user *next;
148 /* MANAGEMENT FUNCTIONS for FAKEHOST STRUCTS */
149 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh);
150 static void hs_del_manager(struct hs_manager *manager, int remove_from_object);
151 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh);
152 static void hs_del_user(struct hs_user *user);
154 static void hs_free_all() {
155 struct hs_toplevel *tlfh, *next_tlfh;
156 struct hs_secondlevel *slfh, *next_slfh;
157 struct hs_assignment *assng, *next_assng;
158 struct hs_manager *manager, *next_manager;
159 struct hs_user *user, *next_user;
160 for(tlfh = toplevels; tlfh; tlfh = next_tlfh) {
161 next_tlfh = tlfh->next;
162 for(manager = tlfh->managers; manager; manager = next_manager) {
163 next_manager = manager->next;
166 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
167 next_slfh = slfh->next;
168 for(manager = tlfh->managers; manager; manager = next_manager) {
169 next_manager = manager->next;
172 for(assng = slfh->assignments; assng; assng = next_assng) {
173 next_assng = assng->next;
176 free(slfh->fakehost);
179 free(tlfh->fakehost);
182 for(user = hostserv_users; user; user = next_user) {
183 next_user = user->next;
187 hostserv_users = NULL;
190 static struct hs_toplevel *hs_add_toplevel(const char *name) {
191 struct hs_toplevel *tlfh = calloc(1, sizeof(*tlfh));
192 tlfh->fakehost = strdup(name);
193 tlfh->next = toplevels;
198 static void hs_del_toplevel(struct hs_toplevel *tlfh) {
199 //unassign all assignments
200 struct hs_secondlevel *slfh, *next_slfh;
201 struct hs_manager *manager, *next_manager;
202 for(manager = tlfh->managers; manager; manager = next_manager) {
203 next_manager = manager->next;
204 hs_del_manager(manager, 0);
206 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
207 next_slfh = slfh->next;
208 hs_del_secondlevel(slfh, 0);
211 struct hs_toplevel *ctlfh, *last_tlfh = NULL;
212 for(ctlfh = toplevels; ctlfh; ctlfh = ctlfh->next) {
215 last_tlfh->next = ctlfh->next;
217 toplevels = ctlfh->next;
221 free(tlfh->fakehost);
225 static struct hs_secondlevel *hs_add_secondlevel(struct hs_toplevel *tlfh, const char *name) {
226 struct hs_secondlevel *slfh = calloc(1, sizeof(*slfh));
227 slfh->toplevel = tlfh;
228 slfh->fakehost = strdup(name);
229 slfh->next = tlfh->secondlevel;
230 tlfh->secondlevel = slfh;
234 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh) {
235 if(remove_from_tlfh) {
236 struct hs_secondlevel *cslfh, *prev_slfh = NULL;
237 for(cslfh = slfh->toplevel->secondlevel; cslfh; cslfh = cslfh->next) {
240 prev_slfh->next = slfh->next;
242 slfh->toplevel->secondlevel = slfh->next;
248 struct hs_assignment *assng, *next_assng;
249 struct hs_manager *manager, *next_manager;
250 for(manager = slfh->managers; manager; manager = next_manager) {
251 next_manager = manager->next;
252 hs_del_manager(manager, 0);
254 for(assng = slfh->assignments; assng; assng = next_assng) {
255 next_assng = assng->next;
256 hs_del_assignment(assng, 0);
258 free(slfh->fakehost);
262 static struct hs_manager *hs_add_manager_toplevel(struct hs_toplevel *tlfh, struct hs_user *user) {
263 struct hs_manager *manager = calloc(1, sizeof(*manager));
264 manager->user = user;
266 manager->object = tlfh;
267 manager->unext = user->managements;
268 user->managements = manager;
269 manager->next = tlfh->managers;
270 tlfh->managers = manager;
274 static struct hs_manager *hs_add_manager_secondlevel(struct hs_secondlevel *slfh, struct hs_user *user) {
275 struct hs_manager *manager = calloc(1, sizeof(*manager));
276 manager->user = user;
278 manager->object = slfh;
279 manager->unext = user->managements;
280 user->managements = manager;
281 manager->next = slfh->managers;
282 slfh->managers = manager;
286 static void hs_del_manager(struct hs_manager *manager, int remove_from_object) {
287 struct hs_manager *cmanager, *prev_manager = NULL;
288 if(remove_from_object) {
289 if(manager->type == 1) {
290 struct hs_toplevel *tlfh = manager->object;
291 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
292 if(cmanager == manager) {
294 prev_manager->next = manager->next;
296 tlfh->managers = manager->next;
299 prev_manager = cmanager;
301 } else if(manager->type == 2) {
302 struct hs_secondlevel *slfh = manager->object;
303 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
304 if(cmanager == manager) {
306 prev_manager->next = manager->next;
308 slfh->managers = manager->next;
311 prev_manager = cmanager;
316 if(remove_from_object != 2) {
317 for(cmanager = manager->user->managements; cmanager; cmanager = cmanager->unext) {
318 if(cmanager == manager) {
320 prev_manager->unext = manager->unext;
322 manager->user->managements = manager->unext;
325 prev_manager = cmanager;
327 if(manager->user->managements == NULL && manager->user->assignments == NULL)
328 hs_del_user(manager->user);
333 static void hs_activate_assignment(struct hs_user *user, struct hs_assignment *assignment) {
334 struct hs_toplevel *tlfh;
335 struct hs_secondlevel *slfh;
336 struct hs_assignment *assgn;
337 char fakehost[HOSTLEN];
339 assert((!assignment || (assignment->user == user)));
341 if(user->assignments) {
342 for(assgn = assignment->user->assignments; assgn; assgn = assgn->unext)
346 if(user->hi->fakehost) {
347 free(user->hi->fakehost);
348 user->hi->fakehost = NULL;
352 slfh = assignment->secondlevel;
353 tlfh = slfh->toplevel;
354 snprintf(fakehost, sizeof(fakehost), "$.%s.%s", slfh->fakehost, tlfh->fakehost);
355 user->hi->fakehost = strdup(fakehost);
356 assignment->active = 1;
359 apply_fakehost(assignment->user->hi, NULL);
362 static struct hs_assignment *hs_add_assignment(struct hs_secondlevel *slfh, struct hs_user *user) {
363 struct hs_assignment *assignment = calloc(1, sizeof(*assignment));
364 assignment->secondlevel = slfh;
365 assignment->user = user;
366 if(user->assignments == NULL)
367 assignment->active = 1;
368 assignment->next = slfh->assignments;
369 slfh->assignments = assignment;
370 assignment->unext = user->assignments;
371 user->assignments = assignment;
372 if(assignment->active) {
373 hs_activate_assignment(user, assignment);
378 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh) {
379 struct hs_assignment *cassignment, *prev_assignment = NULL;
380 if(remove_from_slfh) {
381 for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) {
382 if(cassignment == assignment) {
384 prev_assignment->next = assignment->next;
386 assignment->secondlevel->assignments = assignment->next;
389 prev_assignment = cassignment;
391 prev_assignment = NULL;
393 if(remove_from_slfh != 2) {
394 prev_assignment = NULL;
395 for(cassignment = assignment->user->assignments; cassignment; cassignment = cassignment->unext) {
396 if(cassignment == assignment) {
398 prev_assignment->unext = assignment->unext;
400 assignment->user->assignments = assignment->unext;
403 prev_assignment = cassignment;
406 if(assignment->active) {
407 /* use another assignment - or fall back to default user host? */
409 if(hostserv_conf.fallback_other_assignment && assignment->user->assignments) {
410 /* try to find another assignment from same slfh first */
411 for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) {
412 if(cassignment != assignment && cassignment->user == assignment->user)
415 /* use another tlfh assignment */
417 cassignment = assignment->user->assignments;
419 hs_activate_assignment(assignment->user, cassignment);
422 if(assignment->user->managements == NULL && assignment->user->assignments == NULL)
423 hs_del_user(assignment->user);
428 static struct hs_assignment *hs_get_assignment(struct hs_secondlevel *slfh, struct hs_user *user) {
429 struct hs_assignment *cassignment;
430 for(cassignment = slfh->assignments; cassignment; cassignment = cassignment->next) {
431 if(cassignment->user == user)
437 static struct hs_user *hs_get_user(struct handle_info *hi, int create) {
438 struct hs_user *cuser;
439 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
444 cuser = calloc(1, sizeof(*cuser));
446 cuser->next = hostserv_users;
447 hostserv_users = cuser;
453 static void hs_del_user(struct hs_user *user) {
454 if(user->managements) {
455 struct hs_manager *manager, *next_manager;
456 for(manager = user->managements; manager; manager = next_manager) {
457 next_manager = manager->unext;
458 hs_del_manager(manager, 2);
461 if(user->assignments) {
462 struct hs_assignment *assng, *next_assng;
463 for(assng = user->assignments; assng; assng = next_assng) {
464 next_assng = assng->unext;
465 hs_del_assignment(assng, 2);
468 struct hs_user *cuser, *prev_user = NULL;
469 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
472 prev_user->next = user->next;
474 hostserv_users = user->next;
482 /* END OF MANAGEMENT FUNCTIONS */
484 static int check_management_access(struct handle_info *hi, struct hs_toplevel *tlfh, struct hs_secondlevel *slfh) {
487 if(hi->opserv_level >= hostserv_conf.toplevel_access)
489 struct hs_user *user = hs_get_user(hi, 0);
492 struct hs_manager *manager;
494 for(manager = user->managements; manager; manager = manager->next) {
495 if(manager->type == 2 && manager->object == slfh)
500 for(manager = user->managements; manager; manager = manager->next) {
501 if(manager->type == 1 && manager->object == tlfh)
509 static void cmd_view_toplevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_toplevel *tlfh) {
510 reply("HSMSG_TOPLEVEL_FAKEHOSTS", tlfh->fakehost);
511 struct hs_secondlevel *slfh;
512 if(!tlfh->secondlevel)
513 reply("HSMSG_ASSIGNED_NONE");
515 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
516 struct hs_manager *cmanager;
518 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next)
520 struct hs_assignment *assignment;
522 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
524 reply("HSMSG_TOPLEVEL_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments, managers);
526 reply("HSMSG_MANAGERS_TOPLEVEL", tlfh->fakehost);
527 struct hs_manager *cmanager;
529 reply("HSMSG_ASSIGNED_NONE");
531 char managerBuf[351];
533 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
534 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
535 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
538 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
540 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
544 static void cmd_view_secondlevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_secondlevel *slfh) {
545 reply("HSMSG_FAKEHOST_ASSIGNMENTS", slfh->fakehost, slfh->toplevel->fakehost);
546 struct hs_assignment *assignment;
547 for(assignment = slfh->assignments; assignment; assignment = assignment->next) {
548 reply((assignment->active ? "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE" : "HSMSG_FAKEHOST_ASSIGNMENT"), assignment->user->hi->handle, assignment->user->hi->handle, slfh->fakehost, slfh->toplevel->fakehost);
550 reply("HSMSG_MANAGERS_FAKEHOST", slfh->fakehost, slfh->toplevel->fakehost);
551 struct hs_manager *cmanager;
553 reply("HSMSG_ASSIGNED_NONE");
555 char managerBuf[351];
557 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
558 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
559 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
562 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
564 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
568 static MODCMD_FUNC(cmd_view) {
569 struct handle_info *hi;
570 if(argc >= 2 && !strchr(argv[1], '.')) {
571 if (!(hi = modcmd_get_handle_info(user, argv[1])))
573 } else if(argc >= 2) {
574 if (!(hi = user->handle_info)) {
575 reply("NSMSG_MUST_AUTH");
578 char *slfh_name = argv[1];
579 char *tlfh_name = strchr(argv[1], '.');
582 if(strchr(tlfh_name, '.')) {
583 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
586 struct hs_toplevel *tlfh;
587 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
588 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
591 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
594 if(!irccasecmp(slfh_name, "*")) {
595 if(!check_management_access(hi, tlfh, NULL)) {
596 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
599 cmd_view_toplevel_information(user, cmd, tlfh);
602 struct hs_secondlevel *slfh;
603 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
604 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
606 if(!slfh || !check_management_access(hi, tlfh, slfh)) {
607 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
610 cmd_view_secondlevel_information(user, cmd, slfh);
614 if (!(hi = user->handle_info)) {
615 reply("NSMSG_MUST_AUTH");
619 struct hs_user *huser = hs_get_user(hi, 0);
620 reply("HSMSG_ASSIGNED_FAKEHOSTS", hi->handle);
623 struct hs_assignment *assignment;
624 for(assignment = huser->assignments; assignment; assignment = assignment->unext) {
625 reply((assignment->active ? "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE" : "HSMSG_ASSIGNED_FAKEHOST"), assignment->secondlevel->fakehost, assignment->secondlevel->toplevel->fakehost);
628 if(assigncount && huser->hi == user->handle_info)
629 reply("HSMSG_ASSIGN_HOWTO");
632 reply("HSMSG_ASSIGNED_NONE");
633 if(user->handle_info == hi && hi->opserv_level >= hostserv_conf.toplevel_access) {
634 struct hs_toplevel *tlfh;
635 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
636 struct hs_secondlevel *slfh;
637 struct hs_assignment *assignment;
638 int slfhs = 0, assignments = 0;
639 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
641 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
644 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
646 reply("HSMSG_MANAGE_HOWTO");
647 } else if(huser && huser->managements) {
648 reply("HSMSG_MANAGED_FAKEHOSTS", hi->handle);
649 struct hs_manager *manager;
650 for(manager = huser->managements; manager; manager = manager->unext) {
651 if(manager->type == 1) {
652 struct hs_toplevel *tlfh = manager->object;
653 struct hs_secondlevel *slfh;
654 struct hs_assignment *assignment;
655 int slfhs = 0, assignments = 0;
656 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
658 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
661 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
664 for(manager = huser->managements; manager; manager = manager->next) {
665 if(manager->type == 2) {
666 struct hs_secondlevel *slfh = manager->object;
667 struct hs_toplevel *tlfh = slfh->toplevel;
668 //check if the user is already a manager of the tlfh
669 struct hs_manager *cmanager;
670 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
671 if(cmanager->user == huser) break;
673 if(cmanager) continue;
674 struct hs_assignment *assignment;
676 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
678 reply("HSMSG_MANAGED_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments);
681 if(huser->hi == user->handle_info)
682 reply("HSMSG_MANAGE_HOWTO");
687 static MODCMD_FUNC(cmd_addhost) {
688 struct handle_info *hi;
689 struct hs_toplevel *tlfh;
690 struct hs_secondlevel *slfh;
691 if (!(hi = user->handle_info)) {
692 reply("NSMSG_MUST_AUTH");
695 char *slfh_name = argv[1];
696 char *tlfh_name = strchr(argv[1], '.');
698 reply("HSMSG_TOPLEVEL_INVALID", slfh_name);
703 if(strchr(tlfh_name, '.')) {
704 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
707 if(!irccasecmp(slfh_name, "*")) {
708 if(!check_management_access(hi, NULL, NULL)) {
709 reply("HSMSG_ACCESS_DENIED");
712 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
713 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
716 reply("HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", slfh_name, tlfh_name);
719 hs_add_toplevel(tlfh_name);
720 reply("HSMSG_FAKEHOST_TOPLEVEL_ADDED", tlfh_name);
722 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
723 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
726 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
729 if(!check_management_access(hi, tlfh, NULL)) {
730 reply("HSMSG_ACCESS_DENIED");
733 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
734 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
737 reply("HSMSG_FAKEHOST_SECONDLEVEL_ALREADY_EXISTS", slfh_name, tlfh_name);
740 hs_add_secondlevel(tlfh, slfh_name);
741 reply("HSMSG_FAKEHOST_SECONDLEVEL_ADDED", slfh_name, tlfh_name);
746 static MODCMD_FUNC(cmd_delhost) {
747 struct handle_info *hi;
748 if (!(hi = user->handle_info)) {
749 reply("NSMSG_MUST_AUTH");
752 char *slfh_name = argv[1];
753 char *tlfh_name = strchr(argv[1], '.');
756 if(strchr(tlfh_name, '.')) {
757 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
760 struct hs_toplevel *tlfh;
761 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
762 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
765 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
768 if(!irccasecmp(slfh_name, "*")) {
769 if(!check_management_access(hi, (hostserv_conf.manager_can_del_toplevel ? tlfh : NULL), NULL)) { /* manager access is enough to delete whole toplevel? */
770 reply("HSMSG_ACCESS_DENIED");
773 hs_del_toplevel(tlfh);
774 reply("HSMSG_FAKEHOST_TOPLEVEL_DELETED", tlfh_name);
776 struct hs_secondlevel *slfh;
777 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
778 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
781 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
784 if(!check_management_access(hi, tlfh, (hostserv_conf.manager_can_del_secondlevel ? slfh : NULL))) {
785 reply("HSMSG_ACCESS_DENIED");
788 hs_del_secondlevel(slfh, 1);
789 reply("HSMSG_FAKEHOST_SECONDLEVEL_DELETED", slfh_name, tlfh_name);
794 static MODCMD_FUNC(cmd_addmanager) {
795 struct handle_info *hi;
798 if(!strchr(argv[1], '.')) {
799 if (!(hi = modcmd_get_handle_info(user, argv[1])))
803 if (!(hi = modcmd_get_handle_info(user, argv[2])))
807 char *slfh_name = fakehost;
808 char *tlfh_name = strchr(fakehost, '.');
811 if(strchr(tlfh_name, '.')) {
812 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
815 struct hs_toplevel *tlfh;
816 struct hs_secondlevel *slfh = NULL;
817 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
818 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
821 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
824 if(!irccasecmp(slfh_name, "*")) {
825 if(!check_management_access(user->handle_info, tlfh, NULL)) {
826 reply("HSMSG_ACCESS_DENIED");
830 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
831 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
834 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
837 if(!check_management_access(user->handle_info, tlfh, slfh)) {
838 reply("HSMSG_ACCESS_DENIED");
842 struct hs_user *huser = hs_get_user(hi, 1);
843 struct hs_manager *manager;
845 for(manager = huser->managements; manager; manager = manager->next) {
846 if(manager->type == 2 && manager->object == slfh) {
847 reply("HSMSG_MANAGER_ALREADY", hi->handle, slfh_name, tlfh_name);
852 for(manager = huser->managements; manager; manager = manager->next) {
853 if(manager->type == 1 && manager->object == tlfh) {
854 reply("HSMSG_MANAGER_ALREADY", hi->handle, "*", tlfh_name);
859 hs_add_manager_secondlevel(slfh, huser);
861 hs_add_manager_toplevel(tlfh, huser);
862 reply("HSMSG_MANAGER_ADDED", hi->handle, slfh_name, tlfh_name);
868 static MODCMD_FUNC(cmd_delmanager) {
869 struct handle_info *hi;
871 if(!strchr(argv[1], '.')) {
872 if (!(hi = modcmd_get_handle_info(user, argv[1])))
876 if (!(hi = modcmd_get_handle_info(user, argv[2])))
880 char *slfh_name = fakehost;
881 char *tlfh_name = strchr(fakehost, '.');
885 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, "");
889 if(strchr(tlfh_name, '.')) {
890 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
893 struct hs_toplevel *tlfh;
894 struct hs_secondlevel *slfh = NULL;
895 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
896 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
899 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
902 if(!irccasecmp(slfh_name, "*")) {
903 if(!check_management_access(user->handle_info, tlfh, NULL)) {
904 reply("HSMSG_ACCESS_DENIED");
908 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
909 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
912 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
915 if(!check_management_access(user->handle_info, tlfh, slfh)) {
916 reply("HSMSG_ACCESS_DENIED");
920 struct hs_user *huser = hs_get_user(hi, 0);
921 struct hs_manager *manager;
923 reply("HSMSG_MANAGER_NOT", hi->handle, slfh_name, tlfh_name);
927 for(manager = huser->managements; manager; manager = manager->next) {
928 if(manager->type == 2 && manager->object == slfh)
932 reply("HSMSG_MANAGER_NOT", hi->handle, slfh_name, tlfh_name);
936 for(manager = huser->managements; manager; manager = manager->next) {
937 if(manager->type == 1 && manager->object == tlfh)
941 reply("HSMSG_MANAGER_NOT", hi->handle, "*", tlfh_name);
945 hs_del_manager(manager, 1);
946 reply("HSMSG_MANAGER_DELETED", hi->handle, slfh_name, tlfh_name);
950 static MODCMD_FUNC(cmd_set) {
951 struct handle_info *hi;
952 struct hs_user *hs_user;
953 struct hs_assignment *assignment;
954 struct hs_assignment *assgn;
955 struct hs_toplevel *tlfh;
956 struct hs_secondlevel *slfh;
959 if (!(hi = user->handle_info)) {
960 reply("NSMSG_MUST_AUTH");
963 hs_user = hs_get_user(hi, 0);
965 return 0; //nothing to do here
966 if(!strcmp(argv[1], "*")) {
967 hs_activate_assignment(hs_user, NULL);
970 if(!strchr(argv[1], '.')) {
974 char *slfh_name = fakehost;
975 char *tlfh_name = strchr(fakehost, '.');
980 if(!tlfh_name || strchr(tlfh_name, '.')) {
981 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, (tlfh_name ? tlfh_name : ""));
984 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
985 slfh = assignment->secondlevel;
986 tlfh = slfh->toplevel;
987 if(!irccasecmp(tlfh_name, tlfh->fakehost) && !irccasecmp(slfh_name, slfh->fakehost)) {
988 hs_activate_assignment(hs_user, assignment);
989 reply("HSMSG_FAKEHOST_SET_SUCCESS", slfh->fakehost, tlfh->fakehost);
993 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
998 static MODCMD_FUNC(cmd_assign) {
999 struct handle_info *hi;
1001 if(!strchr(argv[1], '.')) {
1002 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1006 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1010 if (!user->handle_info) {
1011 reply("NSMSG_MUST_AUTH");
1014 char *slfh_name = fakehost;
1015 char *tlfh_name = strchr(fakehost, '.');
1019 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, "");
1023 if(strchr(tlfh_name, '.')) {
1024 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1027 struct hs_toplevel *tlfh;
1028 struct hs_secondlevel *slfh;
1029 struct hs_user *hs_user = hs_get_user(hi, 1);
1030 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
1031 if(!irccasecmp(tlfh_name, tlfh->fakehost)) {
1032 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
1033 if(!irccasecmp(slfh_name, slfh->fakehost)) {
1034 if(!check_management_access(user->handle_info, tlfh, slfh)) {
1035 reply("HSMSG_ACCESS_DENIED");
1038 hs_add_assignment(slfh, hs_user);
1039 reply("HSMSG_FAKEHOST_ASSIGN_SUCCESS", slfh_name, tlfh_name);
1045 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1049 static MODCMD_FUNC(cmd_unassign) {
1050 struct handle_info *hi;
1052 if(!strchr(argv[1], '.')) {
1053 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1057 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1061 if (!user->handle_info) {
1062 reply("NSMSG_MUST_AUTH");
1065 char *slfh_name = fakehost;
1066 char *tlfh_name = strchr(fakehost, '.');
1070 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, "");
1074 if(strchr(tlfh_name, '.')) {
1075 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1078 struct hs_assignment *assignment;
1079 struct hs_user *hs_user = hs_get_user(hi, 0);
1081 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1084 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
1085 if(!irccasecmp(slfh_name, assignment->secondlevel->fakehost)) {
1086 if(!irccasecmp(tlfh_name, assignment->secondlevel->toplevel->fakehost)) {
1087 if(!check_management_access(user->handle_info, assignment->secondlevel->toplevel, assignment->secondlevel)) {
1088 reply("HSMSG_ACCESS_DENIED");
1091 hs_del_assignment(assignment, 1);
1092 reply("HSMSG_FAKEHOST_UNASSIGN_SUCCESS", slfh_name, tlfh_name);
1097 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1101 static void hostserv_conf_read(void) {
1105 str = "modules/hostserv";
1106 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1107 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1111 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1112 if(hostserv_conf.nick && strcmp(hostserv_conf.nick, str)) {
1115 hostserv_conf.nick = str;
1117 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1118 hostserv_conf.modes = (str ? str : NULL);
1120 str = database_get_data(conf_node, "toplevel_access", RECDB_QSTRING);
1121 unsigned int toplevel_access = atoi(str);
1122 hostserv_conf.toplevel_access = (toplevel_access ? toplevel_access : 600);
1124 str = database_get_data(conf_node, "fallback_other_assignment", RECDB_QSTRING);
1125 hostserv_conf.fallback_other_assignment = (atoi(str) ? 1 : 0);
1127 str = database_get_data(conf_node, "manager_can_del_toplevel", RECDB_QSTRING);
1128 hostserv_conf.manager_can_del_toplevel = (atoi(str) ? 1 : 0);
1130 str = database_get_data(conf_node, "manager_can_del_secondlevel", RECDB_QSTRING);
1131 hostserv_conf.manager_can_del_secondlevel = (atoi(str) ? 1 : 0);
1133 /*str = database_get_data(conf_node, "description", RECDB_QSTRING);
1134 hostserv_conf.description = (str ? str : NULL);*/
1137 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra));
1138 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra));
1140 static int hostserv_saxdb_read_toplevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1141 struct record_data *rd = data;
1142 struct hs_toplevel *tlfh;
1143 struct hs_manager *managerTL;
1144 struct hs_user *user;
1145 struct dict *object;
1147 if (rd->type == RECDB_OBJECT) {
1148 dict_t db = GET_RECORD_OBJECT(rd);
1151 tlfh = hs_add_toplevel(name);
1153 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1154 for (it = dict_first(object); it; it = iter_next(it)) {
1155 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1156 //rd = iter_data(it);
1157 /* nothing in here, yet */
1158 managerTL = hs_add_manager_toplevel(tlfh, user);
1159 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1160 managerTL->active = 1;
1162 managerTL->active = 0;
1166 if ((object = database_get_data(db, KEY_SECONDLEVEL, RECDB_OBJECT)))
1167 dict_foreach(object, hostserv_saxdb_read_secondlevel, tlfh);
1172 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1173 struct record_data *rd = data;
1174 struct hs_toplevel *tlfh = extra;
1175 struct hs_secondlevel *slfh;
1176 struct hs_manager *managerSL;
1177 struct hs_user *user;
1178 struct dict *object;
1180 if (rd->type == RECDB_OBJECT) {
1181 dict_t db = GET_RECORD_OBJECT(rd);
1184 slfh = hs_add_secondlevel(tlfh, name);
1186 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1187 for (it = dict_first(object); it; it = iter_next(it)) {
1188 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1189 //rd = iter_data(it);
1190 /* nothing in here, yet */
1191 managerSL = hs_add_manager_secondlevel(slfh, user);
1192 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1193 managerSL->active = 1;
1195 managerSL->active = 0;
1199 if ((object = database_get_data(db, KEY_ASSIGNMENTS, RECDB_OBJECT)))
1200 dict_foreach(object, hostserv_saxdb_read_assignments, slfh);
1205 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra)) {
1206 struct record_data *rd = data;
1207 struct hs_secondlevel *slfh = extra;
1208 struct hs_user *user;
1209 struct hs_assignment *assng;
1211 if (rd->type == RECDB_OBJECT) {
1212 dict_t db = GET_RECORD_OBJECT(rd);
1214 user = hs_get_user(get_handle_info(name), 1);
1215 assng = hs_add_assignment(slfh, user);
1217 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1227 hostserv_saxdb_read(struct dict *db)
1229 struct dict *object;
1231 if ((object = database_get_data(db, KEY_TOPLEVEL, RECDB_OBJECT)))
1232 dict_foreach(object, hostserv_saxdb_read_toplevel, NULL);
1238 hostserv_saxdb_write(struct saxdb_context *ctx)
1240 struct hs_toplevel *tlfh;
1241 struct hs_secondlevel *slfh;
1242 struct hs_assignment *assng;
1243 struct hs_manager *manager;
1245 saxdb_start_record(ctx, KEY_TOPLEVEL, 1);
1246 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
1247 saxdb_start_record(ctx, tlfh->fakehost, 1);
1249 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1250 for(manager = tlfh->managers; manager; manager = manager->next) {
1251 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1252 //additional manager information?
1254 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1255 saxdb_end_record(ctx);
1257 saxdb_end_record(ctx);
1259 saxdb_start_record(ctx, KEY_SECONDLEVEL, 1);
1260 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
1261 saxdb_start_record(ctx, slfh->fakehost, 1);
1263 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1264 for(manager = slfh->managers; manager; manager = manager->next) {
1265 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1266 //additional manager information?
1268 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1269 saxdb_end_record(ctx);
1271 saxdb_end_record(ctx);
1273 saxdb_start_record(ctx, KEY_ASSIGNMENTS, 1);
1274 for(assng = slfh->assignments; assng; assng = assng->next) {
1275 saxdb_start_record(ctx, assng->user->hi->handle, 0);
1276 //additional assignment information?
1278 saxdb_write_int(ctx, KEY_ACTIVE, assng->active);
1279 saxdb_end_record(ctx);
1281 saxdb_end_record(ctx);
1283 saxdb_end_record(ctx);
1285 saxdb_end_record(ctx);
1287 saxdb_end_record(ctx);
1289 saxdb_end_record(ctx);
1295 static void hostserv_db_cleanup(void) {
1299 int hostserv_init() {
1300 HS_LOG = log_register_type("HostServ", "file:hostserv.log");
1302 const char *nick, *modes;
1303 if((nick = conf_get_data("modules/hostserv/nick", RECDB_QSTRING))) {
1304 modes = conf_get_data("modules/hostserv/modes", RECDB_QSTRING);
1305 hostserv = AddLocalUser(nick, nick, NULL, "Host Service", modes);
1306 hostserv_service = service_register(hostserv);
1307 hostserv_service->trigger = '*';
1310 conf_register_reload(hostserv_conf_read);
1311 reg_exit_func(hostserv_db_cleanup);
1312 saxdb_register("HostServ", hostserv_saxdb_read, hostserv_saxdb_write);
1313 hostserv_module = module_register("HostServ", HS_LOG, "mod-hostserv.help", NULL);
1314 modcmd_register(hostserv_module, "view", cmd_view, 0, MODCMD_REQUIRE_AUTHED, NULL);
1315 modcmd_register(hostserv_module, "addmanager", cmd_addmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1316 modcmd_register(hostserv_module, "delmanager", cmd_delmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1317 modcmd_register(hostserv_module, "set", cmd_set, 2, MODCMD_REQUIRE_AUTHED, NULL);
1318 modcmd_register(hostserv_module, "assign", cmd_assign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1319 modcmd_register(hostserv_module, "unassign", cmd_unassign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1320 modcmd_register(hostserv_module, "addhost", cmd_addhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1321 modcmd_register(hostserv_module, "delhost", cmd_delhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1322 message_register_table(msgtab);
1326 int hostserv_finalize(void) {
1330 str = "modules/hostserv";
1331 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1332 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1336 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1337 if (str) hostserv_conf.nick = str;
1339 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1340 if (str) hostserv_conf.modes = str;