X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/0ba0bb4ce0134835187db479ab3bf6a46fe5d518..543b8c392c9ce80e4f2bef9124455bda984e9947:/src/privilege.c diff --git a/src/privilege.c b/src/privilege.c index 060cf48..239b779 100644 --- a/src/privilege.c +++ b/src/privilege.c @@ -22,6 +22,7 @@ */ #include +#include "s_conf.h" #include "privilege.h" static rb_dlink_list privilegeset_list = {}; @@ -35,21 +36,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,38 +90,42 @@ 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(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; } struct PrivilegeSet * @@ -110,7 +143,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); @@ -119,3 +157,31 @@ 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; + + set->status |= CONF_ILLEGAL; + /* 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); + } +}