X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/76eca655f921edde2fb8d11bbcb1aafa9b72cbc9..dc34aae05e6e299a6c53c60b728d73ecb88b21bf:/src/privilege.c diff --git a/src/privilege.c b/src/privilege.c index aa6febe..6b2c8b7 100644 --- a/src/privilege.c +++ b/src/privilege.c @@ -22,7 +22,9 @@ */ #include +#include "s_conf.h" #include "privilege.h" +#include "numeric.h" static rb_dlink_list privilegeset_list = {}; @@ -35,21 +37,49 @@ privilegeset_in_set(struct PrivilegeSet *set, const char *priv) return strstr(set->privs, priv) != NULL; } +static struct PrivilegeSet * +privilegeset_get_any(const char *name) +{ + rb_dlink_node *iter; + + s_assert(name != NULL); + + RB_DLINK_FOREACH(iter, privilegeset_list.head) + { + struct PrivilegeSet *set = (struct PrivilegeSet *) iter->data; + + if (!strcasecmp(set->name, name)) + return set; + } + + return NULL; +} + struct PrivilegeSet * privilegeset_set_new(const char *name, const char *privs, PrivilegeFlags flags) { struct PrivilegeSet *set; - s_assert(privilegeset_get(name) == NULL); + set = privilegeset_get_any(name); + if (set != NULL) + { + if (!(set->status & CONF_ILLEGAL)) + ilog(L_MAIN, "Duplicate privset %s", name); + set->status &= ~CONF_ILLEGAL; + rb_free(set->privs); + } + else + { + set = rb_malloc(sizeof(struct PrivilegeSet)); + set->status = 0; + set->refs = 0; + set->name = rb_strdup(name); - set = rb_malloc(sizeof(struct PrivilegeSet)); - set->refs = 1; - set->name = rb_strdup(name); + rb_dlinkAdd(set, &set->node, &privilegeset_list); + } set->privs = rb_strdup(privs); set->flags = flags; - rb_dlinkAdd(set, &set->node, &privilegeset_list); - return set; } @@ -61,46 +91,52 @@ privilegeset_extend(struct PrivilegeSet *parent, const char *name, const char *p s_assert(parent != NULL); s_assert(name != NULL); s_assert(privs != NULL); - s_assert(privilegeset_get(name) == NULL); - set = rb_malloc(sizeof(struct PrivilegeSet)); - set->refs = 1; - set->name = rb_strdup(name); + set = privilegeset_get_any(name); + if (set != NULL) + { + if (!(set->status & CONF_ILLEGAL)) + ilog(L_MAIN, "Duplicate privset %s", name); + set->status &= ~CONF_ILLEGAL; + rb_free(set->privs); + } + else + { + set = rb_malloc(sizeof(struct PrivilegeSet)); + set->status = 0; + set->refs = 0; + set->name = rb_strdup(name); + + rb_dlinkAdd(set, &set->node, &privilegeset_list); + } set->flags = flags; set->privs = rb_malloc(strlen(parent->privs) + 1 + strlen(privs) + 1); - strcpy(parent->privs, set->privs); + strcpy(set->privs, parent->privs); strcat(set->privs, " "); strcat(set->privs, privs); - rb_dlinkAdd(set, &set->node, &privilegeset_list); - return set; } struct PrivilegeSet * privilegeset_get(const char *name) { - rb_dlink_node *iter; - - s_assert(name != NULL); - - RB_DLINK_FOREACH(iter, privilegeset_list.head) - { - struct PrivilegeSet *set = (struct PrivilegeSet *) iter->data; - - if (!strcasecmp(set->name, name)) - return set; - } + struct PrivilegeSet *set; - return NULL; + set = privilegeset_get_any(name); + if (set != NULL && set->status & CONF_ILLEGAL) + set = NULL; + return set; } -void +struct PrivilegeSet * privilegeset_ref(struct PrivilegeSet *set) { s_assert(set != NULL); set->refs++; + + return set; } void @@ -108,7 +144,12 @@ privilegeset_unref(struct PrivilegeSet *set) { s_assert(set != NULL); - if (--set->refs == 0) + if (set->refs > 0) + set->refs--; + else + ilog(L_MAIN, "refs on privset %s is already 0", + set->name); + if (set->refs == 0 && set->status & CONF_ILLEGAL) { rb_dlinkDelete(&set->node, &privilegeset_list); @@ -117,3 +158,54 @@ privilegeset_unref(struct PrivilegeSet *set) rb_free(set); } } + +void +privilegeset_mark_all_illegal(void) +{ + rb_dlink_node *iter; + + RB_DLINK_FOREACH(iter, privilegeset_list.head) + { + struct PrivilegeSet *set = (struct PrivilegeSet *) iter->data; + + /* the "default" privset is special and must remain available */ + if (!strcmp(set->name, "default")) + continue; + + set->status |= CONF_ILLEGAL; + rb_free(set->privs); + set->privs = rb_strdup(""); + /* but do not free it yet */ + } +} + +void +privilegeset_delete_all_illegal(void) +{ + rb_dlink_node *iter, *next; + + RB_DLINK_FOREACH_SAFE(iter, next, privilegeset_list.head) + { + struct PrivilegeSet *set = (struct PrivilegeSet *) iter->data; + + privilegeset_ref(set); + privilegeset_unref(set); + } +} + +void +privilegeset_report(struct Client *source_p) +{ + rb_dlink_node *ptr; + + RB_DLINK_FOREACH(ptr, privilegeset_list.head) + { + struct PrivilegeSet *set = ptr->data; + + /* use RPL_STATSDEBUG for now -- jilles */ + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "O :%s %s", + set->name, + set->privs); + } +}