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"
49 #define KEY_TITLEHOST_SUFFIX "title_suffix"
51 static const struct message_entry msgtab[] = {
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." },
96 const char *hostserv_module_deps[] = { NULL };
97 struct userNode *hostserv;
98 struct helpfile *hostserv_helpfile;
99 static struct module *hostserv_module;
100 static struct service *hostserv_service;
101 static struct log_type *HS_LOG;
102 static struct hs_toplevel *toplevels = NULL;
103 static struct hs_user *hostserv_users = NULL;
104 const char *title_suffix = NULL;
106 /* FAKEHOST STRUCTS */
109 struct hs_manager *managers;
110 struct hs_secondlevel *secondlevel;
111 struct hs_toplevel *next;
114 struct hs_secondlevel {
115 struct hs_toplevel *toplevel;
117 struct hs_manager *managers;
118 struct hs_assignment *assignments;
119 struct hs_secondlevel *next;
122 struct hs_assignment {
123 struct hs_secondlevel *secondlevel;
124 struct hs_user *user;
126 struct hs_assignment *next;
127 struct hs_assignment *unext; /* for hs_user */
134 struct hs_user *user;
135 struct hs_manager *next;
136 struct hs_manager *unext; /* for hs_user */
140 struct handle_info *hi;
141 struct hs_assignment *assignments;
142 struct hs_manager *managements;
143 struct hs_user *next;
146 /* MANAGEMENT FUNCTIONS for FAKEHOST STRUCTS */
147 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh);
148 static void hs_del_manager(struct hs_manager *manager, int remove_from_object);
149 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh);
150 static void hs_del_user(struct hs_user *user);
152 static void apply_fakehost(struct handle_info *handle, struct userNode *user);
155 generate_fakehost(struct handle_info *handle)
157 extern const char *hidden_host_suffix;
158 static char buffer[HOSTLEN+1];
160 if (!handle->fakehost) {
161 snprintf(buffer, sizeof(buffer), "%s.%s", handle->handle, hidden_host_suffix);
163 } else if (handle->fakehost[0] == '.') {
164 /* A leading dot indicates the stored value is actually a title. */
165 snprintf(buffer, sizeof(buffer), "%s.%s.%s", handle->handle, handle->fakehost+1, title_suffix);
167 } else if (handle->fakehost[0] == '$') {
168 /* A leading $ indicates the stored value begins with the user handle. */
169 snprintf(buffer, sizeof(buffer), "%s%s", handle->handle, handle->fakehost+1);
172 return handle->fakehost;
176 generate_fakeident(struct handle_info *handle, struct userNode *user)
178 static char buffer[USERLEN+1];
180 if (!handle->fakeident) {
183 safestrncpy(buffer, user->ident, sizeof(buffer));
186 return handle->fakeident;
190 apply_fakehost(struct handle_info *handle, struct userNode *user)
192 struct userNode *target;
193 char *fakehost, *fakeident;
198 fakehost = generate_fakehost(handle);
201 fakeident = generate_fakeident(handle, user);
202 assign_fakehost(user, fakehost, fakeident, 0, 1);
206 for (target = handle->users; target; target = target->next_authed) {
207 fakeident = generate_fakeident(handle, target);
208 assign_fakehost(target, fakehost, fakeident, 0, 1);
213 static void hs_free_all() {
214 struct hs_toplevel *tlfh, *next_tlfh;
215 struct hs_secondlevel *slfh, *next_slfh;
216 struct hs_assignment *assng, *next_assng;
217 struct hs_manager *manager, *next_manager;
218 struct hs_user *user, *next_user;
219 for(tlfh = toplevels; tlfh; tlfh = next_tlfh) {
220 next_tlfh = tlfh->next;
221 for(manager = tlfh->managers; manager; manager = next_manager) {
222 next_manager = manager->next;
225 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
226 next_slfh = slfh->next;
227 for(manager = tlfh->managers; manager; manager = next_manager) {
228 next_manager = manager->next;
231 for(assng = slfh->assignments; assng; assng = next_assng) {
232 next_assng = assng->next;
235 free(slfh->fakehost);
238 free(tlfh->fakehost);
241 for(user = hostserv_users; user; user = next_user) {
242 next_user = user->next;
246 hostserv_users = NULL;
249 static struct hs_toplevel *hs_add_toplevel(const char *name) {
250 struct hs_toplevel *tlfh = calloc(1, sizeof(*tlfh));
251 tlfh->fakehost = strdup(name);
252 tlfh->next = toplevels;
257 static void hs_del_toplevel(struct hs_toplevel *tlfh) {
258 //unassign all assignments
259 struct hs_secondlevel *slfh, *next_slfh;
260 struct hs_manager *manager, *next_manager;
261 for(manager = tlfh->managers; manager; manager = next_manager) {
262 next_manager = manager->next;
263 hs_del_manager(manager, 0);
265 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
266 next_slfh = slfh->next;
267 hs_del_secondlevel(slfh, 0);
270 struct hs_toplevel *ctlfh, *last_tlfh = NULL;
271 for(ctlfh = toplevels; ctlfh; ctlfh = ctlfh->next) {
274 last_tlfh->next = ctlfh->next;
276 toplevels = ctlfh->next;
280 free(tlfh->fakehost);
284 static struct hs_secondlevel *hs_add_secondlevel(struct hs_toplevel *tlfh, const char *name) {
285 struct hs_secondlevel *slfh = calloc(1, sizeof(*slfh));
286 slfh->toplevel = tlfh;
287 slfh->fakehost = strdup(name);
288 slfh->next = tlfh->secondlevel;
289 tlfh->secondlevel = slfh;
293 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh) {
294 if(remove_from_tlfh) {
295 struct hs_secondlevel *cslfh, *prev_slfh = NULL;
296 for(cslfh = slfh->toplevel->secondlevel; cslfh; cslfh = cslfh->next) {
299 prev_slfh->next = slfh->next;
301 slfh->toplevel->secondlevel = slfh->next;
307 struct hs_assignment *assng, *next_assng;
308 struct hs_manager *manager, *next_manager;
309 for(manager = slfh->managers; manager; manager = next_manager) {
310 next_manager = manager->next;
311 hs_del_manager(manager, 0);
313 for(assng = slfh->assignments; assng; assng = next_assng) {
314 next_assng = assng->next;
315 hs_del_assignment(assng, 0);
317 free(slfh->fakehost);
321 static struct hs_manager *hs_add_manager_toplevel(struct hs_toplevel *tlfh, struct hs_user *user) {
322 struct hs_manager *manager = calloc(1, sizeof(*manager));
323 manager->user = user;
325 manager->object = tlfh;
326 manager->unext = user->managements;
327 user->managements = manager;
328 manager->next = tlfh->managers;
329 tlfh->managers = manager;
333 static struct hs_manager *hs_add_manager_secondlevel(struct hs_secondlevel *slfh, struct hs_user *user) {
334 struct hs_manager *manager = calloc(1, sizeof(*manager));
335 manager->user = user;
337 manager->object = slfh;
338 manager->unext = user->managements;
339 user->managements = manager;
340 manager->next = slfh->managers;
341 slfh->managers = manager;
345 static void hs_del_manager(struct hs_manager *manager, int remove_from_object) {
346 struct hs_manager *cmanager, *prev_manager = NULL;
347 if(remove_from_object) {
348 if(manager->type == 1) {
349 struct hs_toplevel *tlfh = manager->object;
350 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
351 if(cmanager == manager) {
353 prev_manager->next = manager->next;
355 tlfh->managers = manager->next;
358 prev_manager = cmanager;
360 } else if(manager->type == 2) {
361 struct hs_secondlevel *slfh = manager->object;
362 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
363 if(cmanager == manager) {
365 prev_manager->next = manager->next;
367 slfh->managers = manager->next;
370 prev_manager = cmanager;
375 if(remove_from_object != 2) {
376 for(cmanager = manager->user->managements; cmanager; cmanager = cmanager->unext) {
377 if(cmanager == manager) {
379 prev_manager->unext = manager->unext;
381 manager->user->managements = manager->unext;
384 prev_manager = cmanager;
386 if(manager->user->managements == NULL && manager->user->assignments == NULL)
387 hs_del_user(manager->user);
392 static void activateAssignment(struct hs_assignment *assignment) {
393 struct hs_toplevel *tlfh;
394 struct hs_secondlevel *slfh;
395 struct hs_user *hs_user;
396 struct hs_assignment *assgn;
400 hs_user = assignment->user;
401 if(hs_user->assignments) {
402 for(assgn = hs_user->assignments; assgn; assgn = assgn->unext) {
406 slfh = assignment->secondlevel;
407 tlfh = slfh->toplevel;
408 sprintf(fakehost, "%s.%s.%s", prefix, slfh->fakehost, tlfh->fakehost);
409 hs_user->hi->fakehost = strdup(fakehost);
410 apply_fakehost(hs_user->hi, NULL);
411 assignment->active = 1;
414 static struct hs_assignment *hs_add_assignment(struct hs_secondlevel *slfh, struct hs_user *user) {
415 struct hs_assignment *assignment = calloc(1, sizeof(*assignment));
416 assignment->secondlevel = slfh;
417 assignment->user = user;
418 if(user->assignments == NULL)
419 assignment->active = 1;
420 assignment->next = slfh->assignments;
421 slfh->assignments = assignment;
422 assignment->unext = user->assignments;
423 user->assignments = assignment;
424 if(assignment->active) {
425 activateAssignment(assignment);
430 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh) {
431 struct hs_assignment *cassignment, *prev_assignment = NULL;
432 if(remove_from_slfh) {
433 for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) {
434 if(cassignment == assignment) {
436 prev_assignment->next = assignment->next;
438 assignment->secondlevel->assignments = assignment->next;
441 prev_assignment = cassignment;
443 prev_assignment = NULL;
445 if(remove_from_slfh != 2) {
446 prev_assignment = NULL;
447 for(cassignment = assignment->user->assignments; cassignment; cassignment = cassignment->unext) {
448 if(cassignment == assignment) {
450 prev_assignment->unext = assignment->unext;
452 assignment->user->assignments = assignment->unext;
455 prev_assignment = cassignment;
458 if(assignment->active) {
459 struct handle_info *hi;
461 hi = assignment->user->hi;
463 apply_fakehost(hi, NULL);
466 if(assignment->user->managements == NULL && assignment->user->assignments == NULL)
467 hs_del_user(assignment->user);
472 static struct hs_user *hs_get_user(struct handle_info *hi, int create) {
473 struct hs_user *cuser;
474 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
479 cuser = calloc(1, sizeof(*cuser));
481 cuser->next = hostserv_users;
482 hostserv_users = cuser;
488 static void hs_del_user(struct hs_user *user) {
489 if(user->managements) {
490 struct hs_manager *manager, *next_manager;
491 for(manager = user->managements; manager; manager = next_manager) {
492 next_manager = manager->unext;
493 hs_del_manager(manager, 2);
496 if(user->assignments) {
497 struct hs_assignment *assng, *next_assng;
498 for(assng = user->assignments; assng; assng = next_assng) {
499 next_assng = assng->unext;
500 hs_del_assignment(assng, 2);
503 struct hs_user *cuser, *prev_user = NULL;
504 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
507 prev_user->next = user->next;
509 hostserv_users = user->next;
517 /* END OF MANAGEMENT FUNCTIONS */
519 static int check_management_access(struct handle_info *hi, struct hs_toplevel *tlfh, struct hs_secondlevel *slfh) {
522 if(hi->opserv_level >= hostserv_conf.toplevel_access)
524 struct hs_user *user = hs_get_user(hi, 0);
527 struct hs_manager *manager;
529 for(manager = user->managements; manager; manager = manager->next) {
530 if(manager->type == 2 && manager->object == slfh)
535 for(manager = user->managements; manager; manager = manager->next) {
536 if(manager->type == 1 && manager->object == tlfh)
544 static void cmd_view_toplevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_toplevel *tlfh) {
545 reply("HSMSG_TOPLEVEL_FAKEHOSTS", tlfh->fakehost);
546 struct hs_secondlevel *slfh;
547 if(!tlfh->secondlevel)
548 reply("HSMSG_ASSIGNED_NONE");
550 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
551 struct hs_manager *cmanager;
553 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next)
555 struct hs_assignment *assignment;
557 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
559 reply("HSMSG_TOPLEVEL_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments, managers);
561 reply("HSMSG_MANAGERS_TOPLEVEL", tlfh->fakehost);
562 struct hs_manager *cmanager;
564 reply("HSMSG_ASSIGNED_NONE");
566 char managerBuf[351];
568 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
569 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
570 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
573 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
575 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
579 static void cmd_view_secondlevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_secondlevel *slfh) {
580 reply("HSMSG_FAKEHOST_ASSIGNMENTS", slfh->fakehost, slfh->toplevel->fakehost);
581 struct hs_assignment *assignment;
582 for(assignment = slfh->assignments; assignment; assignment = assignment->next) {
583 reply((assignment->active ? "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE" : "HSMSG_FAKEHOST_ASSIGNMENT"), assignment->user->hi->handle, assignment->user->hi->handle, slfh->fakehost, slfh->toplevel->fakehost);
585 reply("HSMSG_MANAGERS_FAKEHOST", slfh->fakehost, slfh->toplevel->fakehost);
586 struct hs_manager *cmanager;
588 reply("HSMSG_ASSIGNED_NONE");
590 char managerBuf[351];
592 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
593 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
594 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
597 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
599 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
603 static MODCMD_FUNC(cmd_addhost) {
604 struct handle_info *hi;
605 if (!(hi = user->handle_info)) {
606 reply("NSMSG_MUST_AUTH");
609 char *slfh_name = argv[1];
610 char *tlfh_name = strchr(argv[1], '.');
612 reply("HSMSG_TOPLEVEL_INVALID", slfh_name);
617 if(strchr(tlfh_name, '.')) {
618 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
621 if(!irccasecmp(slfh_name, "*")) {
622 if(hi->opserv_level >= hostserv_conf.toplevel_access) {
623 struct hs_toplevel *tlfh;
624 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
625 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
628 reply("HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", slfh_name, tlfh_name);
631 hs_add_toplevel(tlfh_name);
632 reply("HSMSG_FAKEHOST_TOPLEVEL_ADDED", tlfh_name);
635 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
638 struct hs_secondlevel *slfh;
639 struct hs_toplevel *tlfh;
640 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
641 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
644 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
647 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
648 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
651 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
654 if(!check_management_access(hi, tlfh, NULL)) {
655 reply("HSMSG_FAKEHOST_SECONDLEVEL_ALREADY_EXISTS", slfh_name, tlfh_name);
658 hs_add_secondlevel(tlfh, slfh_name);
659 reply("HSMSG_FAKEHOST_SECONDLEVEL_ADDED", slfh_name, tlfh_name);
664 static MODCMD_FUNC(cmd_delhost) {
665 struct handle_info *hi;
666 if (!(hi = user->handle_info)) {
667 reply("NSMSG_MUST_AUTH");
670 char *slfh_name = argv[1];
671 char *tlfh_name = strchr(argv[1], '.');
674 if(strchr(tlfh_name, '.')) {
675 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
678 struct hs_toplevel *tlfh;
679 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
680 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
683 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
686 if(!irccasecmp(slfh_name, "*")) {
687 if(hi->opserv_level < hostserv_conf.toplevel_access) {
688 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
691 hs_del_toplevel(tlfh);
692 reply("HSMSG_FAKEHOST_TOPLEVEL_DELETED", tlfh_name);
695 struct hs_secondlevel *slfh;
696 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
697 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
699 if(!slfh || !check_management_access(hi, tlfh, NULL)) {
700 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
703 hs_del_secondlevel(slfh, 1);
704 reply("HSMSG_FAKEHOST_SECONDLEVEL_DELETED", slfh_name, tlfh_name);
709 static MODCMD_FUNC(cmd_view) {
710 struct handle_info *hi;
711 if(argc >= 2 && !strchr(argv[1], '.')) {
712 if (!(hi = modcmd_get_handle_info(user, argv[1])))
714 } else if(argc >= 2) {
715 if (!(hi = user->handle_info)) {
716 reply("NSMSG_MUST_AUTH");
719 char *slfh_name = argv[1];
720 char *tlfh_name = strchr(argv[1], '.');
723 if(strchr(tlfh_name, '.')) {
724 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
727 struct hs_toplevel *tlfh;
728 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
729 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
732 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
735 if(!irccasecmp(slfh_name, "*")) {
736 if(!check_management_access(hi, tlfh, NULL)) {
737 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
740 cmd_view_toplevel_information(user, cmd, tlfh);
743 struct hs_secondlevel *slfh;
744 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
745 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
747 if(!slfh || !check_management_access(hi, tlfh, slfh)) {
748 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
751 cmd_view_secondlevel_information(user, cmd, slfh);
755 if (!(hi = user->handle_info)) {
756 reply("NSMSG_MUST_AUTH");
760 struct hs_user *huser = hs_get_user(hi, 0);
761 reply("HSMSG_ASSIGNED_FAKEHOSTS", hi->handle);
764 struct hs_assignment *assignment;
765 for(assignment = huser->assignments; assignment; assignment = assignment->unext) {
766 reply((assignment->active ? "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE" : "HSMSG_ASSIGNED_FAKEHOST"), assignment->secondlevel->fakehost, assignment->secondlevel->toplevel->fakehost);
769 if(assigncount && huser->hi == user->handle_info)
770 reply("HSMSG_ASSIGN_HOWTO");
773 reply("HSMSG_ASSIGNED_NONE");
774 if(user->handle_info == hi && hi->opserv_level >= hostserv_conf.toplevel_access) {
775 struct hs_toplevel *tlfh;
776 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
777 struct hs_secondlevel *slfh;
778 struct hs_assignment *assignment;
779 int slfhs = 0, assignments = 0;
780 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
782 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
785 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
787 reply("HSMSG_MANAGE_HOWTO");
788 } else if(huser && huser->managements) {
789 reply("HSMSG_MANAGED_FAKEHOSTS", hi->handle);
790 struct hs_manager *manager;
791 for(manager = huser->managements; manager; manager = manager->unext) {
792 if(manager->type == 1) {
793 struct hs_toplevel *tlfh = manager->object;
794 struct hs_secondlevel *slfh;
795 struct hs_assignment *assignment;
796 int slfhs = 0, assignments = 0;
797 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
799 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
802 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
805 for(manager = huser->managements; manager; manager = manager->next) {
806 if(manager->type == 2) {
807 struct hs_secondlevel *slfh = manager->object;
808 struct hs_toplevel *tlfh = slfh->toplevel;
809 //check if the user is already a manager of the tlfh
810 struct hs_manager *cmanager;
811 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
812 if(cmanager->user == huser) break;
814 if(cmanager) continue;
815 struct hs_assignment *assignment;
817 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
819 reply("HSMSG_MANAGED_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments);
822 if(huser->hi == user->handle_info)
823 reply("HSMSG_MANAGE_HOWTO");
828 static MODCMD_FUNC(cmd_addmanager) {
829 struct handle_info *hi;
832 if(!strchr(argv[1], '.')) {
833 if (!(hi = modcmd_get_handle_info(user, argv[1])))
837 if (!(hi = modcmd_get_handle_info(user, argv[2])))
841 char *slfh_name = fakehost;
842 char *tlfh_name = strchr(fakehost, '.');
845 if(strchr(tlfh_name, '.')) {
846 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
849 struct hs_toplevel *tlfh;
850 struct hs_secondlevel *slfh = NULL;
851 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
852 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
855 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
858 if(!irccasecmp(slfh_name, "*")) {
859 if(!check_management_access(user->handle_info, tlfh, NULL)) {
860 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
864 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
865 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
867 if(!slfh || !check_management_access(user->handle_info, tlfh, slfh)) {
868 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
872 struct hs_user *huser = hs_get_user(hi, 1);
873 struct hs_manager *manager;
875 for(manager = huser->managements; manager; manager = manager->next) {
876 if(manager->type == 2 && manager->object == slfh) {
877 reply("HSMSG_MANAGER_ALREADY", hi->handle, slfh_name, tlfh_name);
882 for(manager = huser->managements; manager; manager = manager->next) {
883 if(manager->type == 1 && manager->object == tlfh) {
884 reply("HSMSG_MANAGER_ALREADY", hi->handle, "*", tlfh_name);
889 hs_add_manager_secondlevel(slfh, huser);
891 hs_add_manager_toplevel(tlfh, huser);
892 reply("HSMSG_MANAGER_ADDED", hi->handle, slfh_name, tlfh_name);
898 static MODCMD_FUNC(cmd_delmanager) {
899 struct handle_info *hi;
901 if(!strchr(argv[1], '.')) {
902 if (!(hi = modcmd_get_handle_info(user, argv[1])))
906 if (!(hi = modcmd_get_handle_info(user, argv[2])))
911 reply("HSMSG_ASSIGNED_NONE");
914 char *slfh_name = fakehost;
915 char *tlfh_name = strchr(fakehost, '.');
919 reply("HSMSG_ASSIGNED_NONE");
923 if(strchr(tlfh_name, '.')) {
924 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
927 struct hs_toplevel *tlfh;
928 struct hs_secondlevel *slfh = NULL;
929 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
930 if(!irccasecmp(tlfh->fakehost, tlfh_name)) break;
933 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
936 if(!irccasecmp(slfh_name, "*")) {
937 if(!check_management_access(user->handle_info, tlfh, NULL)) {
938 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
942 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
943 if(!irccasecmp(slfh->fakehost, slfh_name)) break;
945 if(!slfh || !check_management_access(user->handle_info, tlfh, slfh)) {
946 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
950 struct hs_user *huser = hs_get_user(hi, 0);
951 struct hs_manager *manager;
953 reply("HSMSG_MANAGER_NOT", hi->handle, slfh_name, tlfh_name);
957 for(manager = huser->managements; manager; manager = manager->next) {
958 if(manager->type == 2 && manager->object == slfh)
962 reply("HSMSG_MANAGER_NOT", hi->handle, slfh_name, tlfh_name);
966 for(manager = huser->managements; manager; manager = manager->next) {
967 if(manager->type == 1 && manager->object == tlfh)
971 reply("HSMSG_MANAGER_NOT", hi->handle, "*", tlfh_name);
975 hs_del_manager(manager, 1);
976 reply("HSMSG_MANAGER_DELETED", hi->handle, slfh_name, tlfh_name);
980 static MODCMD_FUNC(cmd_set) {
981 struct handle_info *hi;
982 struct hs_user *hs_user;
983 struct hs_assignment *assignment;
984 struct hs_assignment *assgn;
985 struct hs_toplevel *tlfh;
986 struct hs_secondlevel *slfh;
989 if (!(hi = user->handle_info)) {
990 reply("NSMSG_MUST_AUTH");
993 hs_user = hs_get_user(hi, 0);
994 if(!strcmp(argv[1], "*")) {
996 apply_fakehost(hi, NULL);
997 if(hs_user->assignments) {
998 for(assgn = hs_user->assignments; assgn; assgn = assgn->unext) {
1004 if(!strchr(argv[1], '.')) {
1008 char *slfh_name = fakehost;
1009 char *tlfh_name = strchr(fakehost, '.');
1012 if(strchr(tlfh_name, '.')) {
1013 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1016 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
1017 slfh = assignment->secondlevel;
1018 tlfh = slfh->toplevel;
1019 if(!irccasecmp(slfh_name, slfh->fakehost)) {
1020 if(!irccasecmp(tlfh_name, tlfh->fakehost)) {
1021 activateAssignment(assignment);
1022 reply("HSMSG_FAKEHOST_SET_SUCCESS", slfh->fakehost, tlfh->fakehost);
1027 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1032 static MODCMD_FUNC(cmd_assign) {
1033 struct handle_info *hi;
1034 struct handle_info *hiuser;
1036 if(!strchr(argv[1], '.')) {
1037 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1041 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1045 if (!(hiuser = user->handle_info)) {
1046 reply("NSMSG_MUST_AUTH");
1050 reply("HSMSG_ASSIGNED_NONE");
1053 char *slfh_name = fakehost;
1054 char *tlfh_name = strchr(fakehost, '.');
1058 reply("HSMSG_ASSIGNED_NONE");
1062 if(strchr(tlfh_name, '.')) {
1063 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1066 struct hs_toplevel *tlfh;;
1067 struct hs_secondlevel *slfh;
1068 struct hs_user *hs_user = hs_get_user(hi, 1);
1069 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
1070 if(!irccasecmp(tlfh_name, tlfh->fakehost)) {
1071 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
1072 if(!irccasecmp(slfh_name, slfh->fakehost)) {
1073 if(check_management_access(hiuser, tlfh, slfh)) {
1074 hs_add_assignment(slfh, hs_user);
1075 reply("HSMSG_FAKEHOST_ASSIGN_SUCCESS", slfh_name, tlfh_name);
1078 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1084 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1088 static MODCMD_FUNC(cmd_unassign) {
1089 struct handle_info *hi;
1090 struct handle_info *hiuser;
1092 if(!strchr(argv[1], '.')) {
1093 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1097 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1101 if (!(hiuser = user->handle_info)) {
1102 reply("NSMSG_MUST_AUTH");
1106 reply("HSMSG_ASSIGNED_NONE");
1109 char *slfh_name = fakehost;
1110 char *tlfh_name = strchr(fakehost, '.');
1114 reply("HSMSG_ASSIGNED_NONE");
1118 if(strchr(tlfh_name, '.')) {
1119 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1122 struct hs_assignment *assignment;
1123 struct hs_user *hs_user = hs_get_user(hi, 0);
1124 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
1125 if(!irccasecmp(slfh_name, assignment->secondlevel->fakehost)) {
1126 if(!irccasecmp(tlfh_name, assignment->secondlevel->toplevel->fakehost)) {
1127 if(check_management_access(hiuser, assignment->secondlevel->toplevel, assignment->secondlevel)) {
1128 hs_del_assignment(assignment, 1);
1129 reply("HSMSG_FAKEHOST_UNASSIGN_SUCCESS", slfh_name, tlfh_name);
1132 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1137 reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name);
1141 static void hostserv_conf_read(void)
1146 str = "modules/hostserv";
1147 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1148 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1152 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1153 if(hostserv_conf.nick && strcmp(hostserv_conf.nick, str)) {
1156 hostserv_conf.nick = str;
1158 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1159 hostserv_conf.modes = (str ? str : NULL);
1161 str = database_get_data(conf_node, "toplevel_access", RECDB_QSTRING);
1162 unsigned int toplevel_access = atoi(str);
1163 hostserv_conf.toplevel_access = (toplevel_access ? toplevel_access : 600);
1165 /*str = database_get_data(conf_node, "description", RECDB_QSTRING);
1166 hostserv_conf.description = (str ? str : NULL);*/
1167 str = database_get_data(conf_node, KEY_TITLEHOST_SUFFIX, RECDB_QSTRING);
1168 title_suffix = str ? str : "example.net";
1171 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra));
1172 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra));
1174 static int hostserv_saxdb_read_toplevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1175 struct record_data *rd = data;
1176 struct hs_toplevel *tlfh;
1177 struct hs_manager *managerTL;
1178 struct hs_user *user;
1179 struct dict *object;
1181 if (rd->type == RECDB_OBJECT) {
1182 dict_t db = GET_RECORD_OBJECT(rd);
1185 tlfh = hs_add_toplevel(name);
1187 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1188 for (it = dict_first(object); it; it = iter_next(it)) {
1189 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1190 //rd = iter_data(it);
1191 /* nothing in here, yet */
1192 managerTL = hs_add_manager_toplevel(tlfh, user);
1193 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1194 managerTL->active = 1;
1196 managerTL->active = 0;
1200 if ((object = database_get_data(db, KEY_SECONDLEVEL, RECDB_OBJECT)))
1201 dict_foreach(object, hostserv_saxdb_read_secondlevel, tlfh);
1206 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1207 struct record_data *rd = data;
1208 struct hs_toplevel *tlfh = extra;
1209 struct hs_secondlevel *slfh;
1210 struct hs_manager *managerSL;
1211 struct hs_user *user;
1212 struct dict *object;
1214 if (rd->type == RECDB_OBJECT) {
1215 dict_t db = GET_RECORD_OBJECT(rd);
1218 slfh = hs_add_secondlevel(tlfh, name);
1220 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1221 for (it = dict_first(object); it; it = iter_next(it)) {
1222 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1223 //rd = iter_data(it);
1224 /* nothing in here, yet */
1225 managerSL = hs_add_manager_secondlevel(slfh, user);
1226 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1227 managerSL->active = 1;
1229 managerSL->active = 0;
1233 if ((object = database_get_data(db, KEY_ASSIGNMENTS, RECDB_OBJECT)))
1234 dict_foreach(object, hostserv_saxdb_read_assignments, slfh);
1239 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra)) {
1240 struct record_data *rd = data;
1241 struct hs_secondlevel *slfh = extra;
1242 struct hs_user *user;
1243 struct hs_assignment *assng;
1245 if (rd->type == RECDB_OBJECT) {
1246 dict_t db = GET_RECORD_OBJECT(rd);
1248 user = hs_get_user(get_handle_info(name), 1);
1249 assng = hs_add_assignment(slfh, user);
1251 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1261 hostserv_saxdb_read(struct dict *db)
1263 struct dict *object;
1265 if ((object = database_get_data(db, KEY_TOPLEVEL, RECDB_OBJECT)))
1266 dict_foreach(object, hostserv_saxdb_read_toplevel, NULL);
1272 hostserv_saxdb_write(struct saxdb_context *ctx)
1274 struct hs_toplevel *tlfh;
1275 struct hs_secondlevel *slfh;
1276 struct hs_assignment *assng;
1277 struct hs_manager *manager;
1279 saxdb_start_record(ctx, KEY_TOPLEVEL, 1);
1280 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
1281 saxdb_start_record(ctx, tlfh->fakehost, 1);
1283 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1284 for(manager = tlfh->managers; manager; manager = manager->next) {
1285 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1286 //additional manager information?
1288 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1289 saxdb_end_record(ctx);
1291 saxdb_end_record(ctx);
1293 saxdb_start_record(ctx, KEY_SECONDLEVEL, 1);
1294 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
1295 saxdb_start_record(ctx, slfh->fakehost, 1);
1297 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1298 for(manager = slfh->managers; manager; manager = manager->next) {
1299 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1300 //additional manager information?
1302 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1303 saxdb_end_record(ctx);
1305 saxdb_end_record(ctx);
1307 saxdb_start_record(ctx, KEY_ASSIGNMENTS, 1);
1308 for(assng = slfh->assignments; assng; assng = assng->next) {
1309 saxdb_start_record(ctx, assng->user->hi->handle, 0);
1310 //additional assignment information?
1312 saxdb_write_int(ctx, KEY_ACTIVE, assng->active);
1313 saxdb_end_record(ctx);
1315 saxdb_end_record(ctx);
1317 saxdb_end_record(ctx);
1319 saxdb_end_record(ctx);
1321 saxdb_end_record(ctx);
1323 saxdb_end_record(ctx);
1329 static void hostserv_db_cleanup(void) {
1333 int hostserv_init() {
1334 HS_LOG = log_register_type("HostServ", "file:hostserv.log");
1336 const char *nick, *modes;
1337 if((nick = conf_get_data("modules/hostserv/nick", RECDB_QSTRING))) {
1338 modes = conf_get_data("modules/hostserv/modes", RECDB_QSTRING);
1339 hostserv = AddLocalUser(nick, nick, NULL, "Host Service", modes);
1340 hostserv_service = service_register(hostserv);
1341 hostserv_service->trigger = '*';
1344 conf_register_reload(hostserv_conf_read);
1345 reg_exit_func(hostserv_db_cleanup);
1346 saxdb_register("HostServ", hostserv_saxdb_read, hostserv_saxdb_write);
1347 hostserv_module = module_register("HostServ", HS_LOG, "mod-hostserv.help", NULL);
1348 modcmd_register(hostserv_module, "view", cmd_view, 0, MODCMD_REQUIRE_AUTHED, NULL);
1349 modcmd_register(hostserv_module, "addmanager", cmd_addmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1350 modcmd_register(hostserv_module, "delmanager", cmd_delmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1351 modcmd_register(hostserv_module, "set", cmd_set, 2, MODCMD_REQUIRE_AUTHED, NULL);
1352 modcmd_register(hostserv_module, "assign", cmd_assign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1353 modcmd_register(hostserv_module, "unassign", cmd_unassign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1354 modcmd_register(hostserv_module, "addhost", cmd_addhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1355 modcmd_register(hostserv_module, "delhost", cmd_delhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1356 message_register_table(msgtab);
1360 int hostserv_finalize(void) {
1364 str = "modules/hostserv";
1365 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1366 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1370 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1371 if (str) hostserv_conf.nick = str;
1373 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1374 if (str) hostserv_conf.modes = str;