]> jfr.im git - irc/rqf/shadowircd.git/commitdiff
Make rehashing privset{} change online oper privileges.
authorJilles Tjoelker <redacted>
Sun, 14 Dec 2008 17:25:15 +0000 (18:25 +0100)
committerJilles Tjoelker <redacted>
Sun, 14 Dec 2008 17:25:15 +0000 (18:25 +0100)
This also fixes memory leak due to multiple privsets
with the same name (added after each rehash).

include/privilege.h
src/privilege.c
src/s_conf.c

index c454efca45bd544cc785614b1452b0dd171f8f76..2af53f3eb77639a201aac469f6ce9d095be5fe19 100644 (file)
@@ -31,6 +31,7 @@ typedef enum {
 } PrivilegeFlags;
 
 struct PrivilegeSet {
+       unsigned int status;    /* If CONF_ILLEGAL, delete when no refs */
        int refs;
        char *name;
        char *privs;
@@ -44,5 +45,7 @@ struct PrivilegeSet *privilegeset_extend(struct PrivilegeSet *parent, const char
 struct PrivilegeSet *privilegeset_get(const char *name);
 struct PrivilegeSet *privilegeset_ref(struct PrivilegeSet *set);
 void privilegeset_unref(struct PrivilegeSet *set);
+void privilegeset_mark_all_illegal(void);
+void privilegeset_delete_all_illegal(void);
 
 #endif
index 060cf4895fd5fe488d585485db30e9d174a1f7f2..239b7796d75cd4ba3c207b1968ddf92b8f70379a 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <stdinc.h>
+#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);
+       }
+}
index b78fa51855ed3d69a7426b10328c9218b5d2065b..430ef201595d0689fd6edf834ba99580b127f2b8 100644 (file)
@@ -46,6 +46,7 @@
 #include "reject.h"
 #include "cache.h"
 #include "blacklist.h"
+#include "privilege.h"
 #include "sslproc.h"
 
 struct config_server_hide ConfigServerHide;
@@ -853,6 +854,7 @@ read_conf(FILE * file)
        validate_conf();        /* Check to make sure some values are still okay. */
        /* Some global values are also loaded here. */
        check_class();          /* Make sure classes are valid */
+       privilegeset_delete_all_illegal();
 }
 
 static void
@@ -1253,6 +1255,8 @@ clear_out_old_conf(void)
 
        destroy_blacklists();
 
+       privilegeset_mark_all_illegal();
+
        /* OK, that should be everything... */
 }