X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fmod-hostserv.c;h=3aeddfd306a743c59a31aa104fe4f6dd3875d3ac;hb=0167bfd9ee798a96959befd10230dcce72b7ae41;hp=55ac89e928e5cd7bd957a4c42ea5c2b7236cabb0;hpb=a21e92ca57d7b82dcb540d9ec1c85ed709a28591;p=srvx.git diff --git a/src/mod-hostserv.c b/src/mod-hostserv.c index 55ac89e..3aeddfd 100644 --- a/src/mod-hostserv.c +++ b/src/mod-hostserv.c @@ -29,6 +29,8 @@ * "manager_can_del_toplevel" "0"; //managers of a toplevel group may delete the whole group * "manager_can_rename_secondlevel" "0"; //managers of a secondlevel group may rename the whole group * "manager_can_del_secondlevel" "0"; //managers of a secondlevel group may delete the whole group + * "manager_toplevel_can_oset" "0"; //managers of a toplevel group can set other user's fakehosts + * "manager_secondlevel_can_oset" "0"; //managers of a secondlevel group can set other user's fakehosts * }; * }; * @@ -38,7 +40,7 @@ */ #include "chanserv.h" -#include "opserv.h" +#include "opserv.h" /* devnull management! */ #include "nickserv.h" #include "conf.h" #include "modcmd.h" @@ -50,6 +52,7 @@ #define KEY_MANAGERS "Manager" #define KEY_ASSIGNMENTS "Assignments" #define KEY_ACTIVE "active" +#define KEY_DEVNULL "devnull" #define HS_FAKEHOST_SPECIAL_CHARS "_-:;" /* alphanum already included */ @@ -77,6 +80,7 @@ static const struct message_entry msgtab[] = { { "HSMSG_UNKNOWN_FAKEHOST", "Fakehost $b%s.%s$b is unknown or you have no access to manage it." }, { "HSMSG_TOPLEVEL_FAKEHOSTS", "Fakehosts in group $b*.%s$b:" }, { "HSMSG_TOPLEVEL_FAKEHOST", " $b%s.%s$b assignments: %d managers: %d" }, + { "HSMSG_TOPLEVEL_FAKEHOST_DEVNULL", " $b%s.%s$b assignments: %d managers: %d DevNull: %s" }, { "HSMSG_TOPLEVEL_INVALID", "The name of the group you entered is invalid ($b%s$b)" }, { "HSMSG_MANAGERS_TOPLEVEL", "Managers of group $b*.%s$b:" }, { "HSMSG_MANAGERS_FAKEHOST", "Managers of group $b%s.%s$b:" }, @@ -99,6 +103,8 @@ static const struct message_entry msgtab[] = { { "HSMSG_FAKEHOST_ASSIGN_SUCCESS", "Group $b%s.%s$b was assigned successfully." }, { "HSMSG_FAKEHOST_ASSIGNED", "Group $b%s.%s$b is already assigned to the user." }, { "HSMSG_FAKEHOST_UNASSIGN_SUCCESS", "Group $b%s.%s$b was unassigned successfully." }, + { "HSMSG_FAKEHOST_TLDEVNULL", "You can't assign a DevNull class to a toplevel fakehost." }, + { "HSMSG_DEVNULL_CLASS", "$b%s.%s$b DevNull Class: %s" }, { NULL, NULL } }; @@ -112,6 +118,8 @@ static struct { int manager_can_del_secondlevel : 1; int manager_can_rename_toplevel : 1; int manager_can_rename_secondlevel : 1; + int manager_toplevel_can_oset : 1; + int manager_secondlevel_can_oset : 1; } hostserv_conf; const char *hostserv_module_deps[] = { NULL }; @@ -135,6 +143,7 @@ struct hs_secondlevel { struct hs_toplevel *toplevel; char *fakehost; struct hs_manager *managers; + int devnull_id; struct hs_assignment *assignments; struct hs_secondlevel *next; }; @@ -642,7 +651,11 @@ static void cmd_view_toplevel_information(UNUSED_ARG(struct userNode *user), UNU int assignments = 0; for(assignment = slfh->assignments; assignment; assignment = assignment->next) assignments++; - reply("HSMSG_TOPLEVEL_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments, managers); + struct devnull_class *th; + if(slfh->devnull_id && (th = devnull_find_id(slfh->devnull_id))) + reply("HSMSG_TOPLEVEL_FAKEHOST_DEVNULL", slfh->fakehost, tlfh->fakehost, assignments, managers, th->name); + else + reply("HSMSG_TOPLEVEL_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments, managers); } reply("HSMSG_MANAGERS_TOPLEVEL", tlfh->fakehost); struct hs_manager *cmanager; @@ -770,13 +783,13 @@ static MODCMD_FUNC(cmd_view) { reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments); } } - for(manager = huser->managements; manager; manager = manager->next) { + for(manager = huser->managements; manager; manager = manager->unext) { if(manager->type == 2) { struct hs_secondlevel *slfh = manager->object; struct hs_toplevel *tlfh = slfh->toplevel; //check if the user is already a manager of the tlfh struct hs_manager *cmanager; - for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) { + for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->unext) { if(cmanager->user == huser) break; } if(cmanager) continue; @@ -967,8 +980,20 @@ static MODCMD_FUNC(cmd_addmanager) { } if(fhinfo.slfh) hs_add_manager_secondlevel(fhinfo.slfh, huser); - else + else { hs_add_manager_toplevel(fhinfo.tlfh, huser); + //remove from all slfh's + struct hs_manager *next_manager; + struct hs_secondlevel *slfh; + for(manager = huser->managements; manager; manager = next_manager) { + next_manager = manager->next; + if(manager->type == 2) { + slfh = manager->object; + if(slfh->toplevel == fhinfo.tlfh) + hs_del_manager(manager, 1); + } + } + } reply("HSMSG_MANAGER_ADDED", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name); return 1; } @@ -1148,6 +1173,151 @@ static MODCMD_FUNC(cmd_unassign) { return 1; } +static MODCMD_FUNC(cmd_oset) { + struct handle_info *hi; + char *fakehost; + struct hs_assignment *assignment; + if(!strchr(argv[1], '.') && strcmp(argv[1], "*")) { + if (!(hi = modcmd_get_handle_info(user, argv[1]))) + return 0; + fakehost = argv[2]; + } else { + if (!(hi = modcmd_get_handle_info(user, argv[2]))) + return 0; + fakehost = argv[1]; + } + if (!user->handle_info) { + reply("NSMSG_MUST_AUTH"); + return 0; + } + struct hs_user *hs_user = hs_get_user(hi, 1); + for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) { + if(assignment->active) + break; + } + if(assignment && !check_management_access(user->handle_info, (hostserv_conf.manager_toplevel_can_oset ? assignment->secondlevel->toplevel : NULL), (hostserv_conf.manager_secondlevel_can_oset ? assignment->secondlevel : NULL))) { + reply("HSMSG_ACCESS_DENIED"); + return 0; + } + if(!strcmp(fakehost, "*")) { + if(!assignment) + return 0; //simply ignore (there is no assignment in use) + hs_activate_assignment(hs_user, NULL); + return 1; + } else { + struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1); + if(fhinfo.parse_state == HS_FHPARSE_INVALID) { + reply("HSMSG_TOPLEVEL_INVALID", fakehost); + return 0; + } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN || !fhinfo.slfh) { + reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name); + return 0; + } + if(!check_management_access(user->handle_info, (hostserv_conf.manager_toplevel_can_oset ? fhinfo.tlfh : NULL), (hostserv_conf.manager_secondlevel_can_oset ? fhinfo.slfh : NULL))) { + reply("HSMSG_ACCESS_DENIED"); + return 0; + } + struct hs_toplevel *tlfh; + struct hs_secondlevel *slfh; + for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) { + slfh = assignment->secondlevel; + tlfh = slfh->toplevel; + if(tlfh == fhinfo.tlfh && slfh == fhinfo.slfh) { + hs_activate_assignment(hs_user, assignment); + reply("HSMSG_FAKEHOST_SET_SUCCESS", slfh->fakehost, tlfh->fakehost); + return 1; + } + } + reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name); + return 0; + } +} + +static MODCMD_FUNC(cmd_setdevnull) { + struct handle_info *hi; + if (!(hi = user->handle_info)) { + reply("NSMSG_MUST_AUTH"); + return 0; + } + struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1); + if(fhinfo.parse_state == HS_FHPARSE_INVALID) { + reply("HSMSG_TOPLEVEL_INVALID", argv[1]); + return 0; + } + if(!fhinfo.have_secondlevel) { + reply("HSMSG_FAKEHOST_TLDEVNULL"); + return 0; + } else { + if(!fhinfo.tlfh) { + reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name); + return 0; + } + if(!check_management_access(hi, NULL, NULL)) { + reply("HSMSG_ACCESS_DENIED"); + return 0; + } + char *fakehost_name; + if(!strcmp(argv[2], "*")) { + fhinfo.slfh->devnull_id = 0; + fakehost_name = "-"; + } else { + struct devnull_class *th = devnull_find_name(argv[2]); + if(!th) { + reply("OSMSG_DEVNULL_NOTFOUND", argv[2]); + return 0; + } + fhinfo.slfh->devnull_id = th->id; + fakehost_name = th->name; + } + reply("HSMSG_DEVNULL_CLASS", fhinfo.slfh_name, fhinfo.tlfh_name, fakehost_name); + } + return 1; +} + + +struct devnull_class hostserv_get_user_priv(struct handle_info *hi) { + struct devnull_class th; + memset(&th, 0, sizeof(th)); + + struct hs_user *huser = hs_get_user(hi, 0); + if(huser) { + struct devnull_class *devc; + if(hi->devnull_id != 0) { + devc = devnull_find_id(huser->hi->devnull_id); + if(devc) { + if(DEVNULL_HAS_PRIV(devc, CHANLIMIT) && (!DEVNULL_HAS_PRIV(&th, CHANLIMIT) || th.maxchan < devc->maxchan)) + th.maxchan = devc->maxchan; + if(DEVNULL_HAS_PRIV(devc, MAXSENDQ) && (!DEVNULL_HAS_PRIV(&th, MAXSENDQ) || th.maxsendq < devc->maxsendq)) + th.maxsendq = devc->maxsendq; + th.modes |= devc->modes; + if(!th.name) + th.name = devc->name; + } + } else { + struct hs_assignment *assignment; + struct hs_secondlevel *slfh; + for(assignment = huser->assignments; assignment; assignment = assignment->unext) { + slfh = assignment->secondlevel; + if(slfh->devnull_id) { + devc = devnull_find_id(slfh->devnull_id); + if(!devc) { + slfh->devnull_id = 0; + continue; + } + if(DEVNULL_HAS_PRIV(devc, CHANLIMIT) && (!DEVNULL_HAS_PRIV(&th, CHANLIMIT) || th.maxchan < devc->maxchan)) + th.maxchan = devc->maxchan; + if(DEVNULL_HAS_PRIV(devc, MAXSENDQ) && (!DEVNULL_HAS_PRIV(&th, MAXSENDQ) || th.maxsendq < devc->maxsendq)) + th.maxsendq = devc->maxsendq; + th.modes |= devc->modes; + if(!th.name) + th.name = devc->name; + } + } + } + } + return th; +} + static void hostserv_conf_read(void) { dict_t conf_node; const char *str; @@ -1168,26 +1338,29 @@ static void hostserv_conf_read(void) { hostserv_conf.modes = (str ? str : NULL); str = database_get_data(conf_node, "toplevel_access", RECDB_QSTRING); - unsigned int toplevel_access = atoi(str); + unsigned int toplevel_access = (str ? atoi(str) : 0); hostserv_conf.toplevel_access = (toplevel_access ? toplevel_access : 600); str = database_get_data(conf_node, "fallback_other_assignment", RECDB_QSTRING); - hostserv_conf.fallback_other_assignment = (atoi(str) ? 1 : 0); + hostserv_conf.fallback_other_assignment = (str && atoi(str) ? 1 : 0); str = database_get_data(conf_node, "manager_can_del_toplevel", RECDB_QSTRING); - hostserv_conf.manager_can_del_toplevel = (atoi(str) ? 1 : 0); + hostserv_conf.manager_can_del_toplevel = (str && atoi(str) ? 1 : 0); str = database_get_data(conf_node, "manager_can_del_secondlevel", RECDB_QSTRING); - hostserv_conf.manager_can_del_secondlevel = (atoi(str) ? 1 : 0); + hostserv_conf.manager_can_del_secondlevel = (str && atoi(str) ? 1 : 0); str = database_get_data(conf_node, "manager_can_rename_toplevel", RECDB_QSTRING); - hostserv_conf.manager_can_rename_toplevel = (atoi(str) ? 1 : 0); + hostserv_conf.manager_can_rename_toplevel = (str && atoi(str) ? 1 : 0); str = database_get_data(conf_node, "manager_can_rename_secondlevel", RECDB_QSTRING); - hostserv_conf.manager_can_rename_secondlevel = (atoi(str) ? 1 : 0); + hostserv_conf.manager_can_rename_secondlevel = (str && atoi(str) ? 1 : 0); + + str = database_get_data(conf_node, "manager_toplevel_can_oset", RECDB_QSTRING); + hostserv_conf.manager_toplevel_can_oset = (str && atoi(str) ? 1 : 0); - /*str = database_get_data(conf_node, "description", RECDB_QSTRING); - hostserv_conf.description = (str ? str : NULL);*/ + str = database_get_data(conf_node, "manager_secondlevel_can_oset", RECDB_QSTRING); + hostserv_conf.manager_secondlevel_can_oset = (str && atoi(str) ? 1 : 0); } static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra)); @@ -1232,6 +1405,7 @@ static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ struct hs_manager *managerSL; struct hs_user *user; struct dict *object; + char *str; if (rd->type == RECDB_OBJECT) { dict_t db = GET_RECORD_OBJECT(rd); @@ -1239,6 +1413,10 @@ static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ slfh = hs_add_secondlevel(tlfh, name); + str = database_get_data(db, KEY_DEVNULL, RECDB_QSTRING); + if(str) + slfh->devnull_id = atoi(str); + if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) { for (it = dict_first(object); it; it = iter_next(it)) { user = hs_get_user(get_handle_info(iter_key(it)), 1); @@ -1313,6 +1491,9 @@ hostserv_saxdb_write(struct saxdb_context *ctx) for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) { saxdb_start_record(ctx, slfh->fakehost, 1); + if(slfh->devnull_id) + saxdb_write_int(ctx, KEY_DEVNULL, slfh->devnull_id); + saxdb_start_record(ctx, KEY_MANAGERS, 1); for(manager = slfh->managers; manager; manager = manager->next) { saxdb_start_record(ctx, manager->user->hi->handle, 0); @@ -1349,6 +1530,13 @@ static void hostserv_db_cleanup(void) { hs_free_all(); } +static void hostserv_unreg_account(UNUSED_ARG(struct userNode *user), struct handle_info *handle) { + struct hs_user *huser = hs_get_user(handle, 0); + if (huser) { + hs_del_user(huser); + } +} + int hostserv_init() { HS_LOG = log_register_type("HostServ", "file:hostserv.log"); @@ -1361,6 +1549,7 @@ int hostserv_init() { } conf_register_reload(hostserv_conf_read); + reg_unreg_func(hostserv_unreg_account); reg_exit_func(hostserv_db_cleanup); saxdb_register("HostServ", hostserv_saxdb_read, hostserv_saxdb_write); hostserv_module = module_register("HostServ", HS_LOG, "mod-hostserv.help", NULL); @@ -1373,7 +1562,12 @@ int hostserv_init() { modcmd_register(hostserv_module, "addhost", cmd_addhost, 2, MODCMD_REQUIRE_AUTHED, NULL); modcmd_register(hostserv_module, "delhost", cmd_delhost, 2, MODCMD_REQUIRE_AUTHED, NULL); modcmd_register(hostserv_module, "renamehost", cmd_renamehost, 3, MODCMD_REQUIRE_AUTHED, NULL); + modcmd_register(hostserv_module, "oset", cmd_oset, 3, MODCMD_REQUIRE_AUTHED, NULL); + modcmd_register(hostserv_module, "setdevnull", cmd_setdevnull, 3, MODCMD_REQUIRE_AUTHED, NULL); message_register_table(msgtab); + + /* "register" own devnull privilege handler */ + devnull_check_priv_func = hostserv_get_user_priv; return 1; }