* "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
* };
* };
*
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 };
/* temporary structs */
struct hs_fakehost_info {
- int parse_state;
+ unsigned int parse_state : 4;
+ unsigned int have_secondlevel : 1;
char *tlfh_name;
char *slfh_name;
struct hs_toplevel *tlfh;
struct hs_fakehost_info parse_fakehost_info(char *fakehost, int fix_name_case) {
struct hs_fakehost_info fhinfo;
int i;
+ memset(&fhinfo, 0, sizeof(fhinfo));
for(i = strlen(fakehost)-1; i >= 0; i--) {
- if(!isalnum(fakehost[i]) && !strchr(HS_FAKEHOST_SPECIAL_CHARS, fakehost[i])) {
+ if(!isalnum(fakehost[i]) && fakehost[i] != '.' && !(fakehost[i] == '*' && i == 0) && !strchr(HS_FAKEHOST_SPECIAL_CHARS, fakehost[i])) {
fhinfo.parse_state = HS_FHPARSE_INVALID;
return fhinfo;
}
fhinfo.tlfh_name[0] = '\0';
return fhinfo;
}
- if(!irccasecmp(fhinfo.slfh_name, "*"))
- fhinfo.slfh_name = NULL;
+ if(irccasecmp(fhinfo.slfh_name, "*"))
+ fhinfo.have_secondlevel = 1;
struct hs_toplevel *tlfh;
struct hs_secondlevel *slfh;
for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
fhinfo.parse_state = HS_FHPARSE_UNKNOWN;
return fhinfo;
}
- if(fhinfo.slfh_name) {
+ if(fhinfo.have_secondlevel) {
for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
if(!irccasecmp(slfh->fakehost, fhinfo.slfh_name)) break;
}
if(fix_name_case) {
//simply copy the stored fakehosts over the given ones
strcpy(fhinfo.tlfh_name, fhinfo.tlfh->fakehost);
- strcpy(fhinfo.slfh_name, fhinfo.slfh->fakehost);
+ if(fhinfo.slfh)
+ strcpy(fhinfo.slfh_name, fhinfo.slfh->fakehost);
}
fhinfo.parse_state = HS_FHPARSE_SUCCESS;
return fhinfo;
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;
reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
return 0;
}
- if(!fhinfo.slfh_name) {
+ if(!fhinfo.have_secondlevel) {
if(!check_management_access(hi, NULL, NULL)) {
reply("HSMSG_ACCESS_DENIED");
return 0;
if(new_fhinfo.parse_state == HS_FHPARSE_INVALID) {
reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
return 0;
- } else if(new_fhinfo.parse_state != HS_FHPARSE_UNKNOWN && (irccasecmp(fhinfo.tlfh_name, new_fhinfo.tlfh_name) || (new_fhinfo.slfh && new_fhinfo.slfh_name && irccasecmp(fhinfo.slfh_name, new_fhinfo.slfh_name)))) {
+ } else if(new_fhinfo.parse_state != HS_FHPARSE_UNKNOWN && (irccasecmp(fhinfo.tlfh_name, new_fhinfo.tlfh_name) || (new_fhinfo.slfh && irccasecmp(fhinfo.slfh_name, new_fhinfo.slfh_name)))) {
reply("HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", new_fhinfo.slfh_name, new_fhinfo.tlfh_name);
return 0;
}
reply("HSMSG_ACCESS_DENIED");
return 0;
}
- if(new_fhinfo.slfh_name) {
+ if(fhinfo.have_secondlevel) {
//can't rename toplevel into secondlevel fakehost!
new_fhinfo.tlfh_name--;
new_fhinfo.tlfh_name[0] = '.';
}
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;
}
return 0;
}
if(fhinfo.slfh) {
- for(manager = huser->managements; manager; manager = manager->next) {
+ for(manager = huser->managements; manager; manager = manager->unext) {
if(manager->type == 2 && manager->object == fhinfo.slfh)
break;
}
return 0;
}
} else {
- for(manager = huser->managements; manager; manager = manager->next) {
+ for(manager = huser->managements; manager; manager = manager->unext) {
if(manager->type == 1 && manager->object == fhinfo.tlfh)
break;
}
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 void hostserv_conf_read(void) {
dict_t conf_node;
const char *str;
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));
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);
message_register_table(msgtab);
return 1;
}