]> jfr.im git - solanum.git/blob - ircd/privilege.c
Resolve shfit/reduce conflict in timespec production (#54)
[solanum.git] / ircd / privilege.c
1 /*
2 * Solanum: a slightly advanced ircd
3 * privilege.c: Dynamic privileges API.
4 *
5 * Copyright (c) 2008 William Pitcock <nenolod@dereferenced.org>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice is present in all copies.
10 *
11 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
12 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
15 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
19 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
20 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21 * POSSIBILITY OF SUCH DAMAGE.
22 */
23
24 #include <stdinc.h>
25 #include "s_conf.h"
26 #include "privilege.h"
27 #include "numeric.h"
28 #include "s_assert.h"
29 #include "logger.h"
30 #include "send.h"
31
32 static rb_dlink_list privilegeset_list = {NULL, NULL, 0};
33
34 int
35 privilegeset_in_set(struct PrivilegeSet *set, const char *priv)
36 {
37 s_assert(set != NULL);
38 s_assert(priv != NULL);
39
40 return strstr(set->privs, priv) != NULL;
41 }
42
43 static struct PrivilegeSet *
44 privilegeset_get_any(const char *name)
45 {
46 rb_dlink_node *iter;
47
48 s_assert(name != NULL);
49
50 RB_DLINK_FOREACH(iter, privilegeset_list.head)
51 {
52 struct PrivilegeSet *set = (struct PrivilegeSet *) iter->data;
53
54 if (!rb_strcasecmp(set->name, name))
55 return set;
56 }
57
58 return NULL;
59 }
60
61 struct PrivilegeSet *
62 privilegeset_set_new(const char *name, const char *privs, PrivilegeFlags flags)
63 {
64 struct PrivilegeSet *set;
65
66 set = privilegeset_get_any(name);
67 if (set != NULL)
68 {
69 if (!(set->status & CONF_ILLEGAL))
70 ilog(L_MAIN, "Duplicate privset %s", name);
71 set->status &= ~CONF_ILLEGAL;
72 rb_free(set->privs);
73 }
74 else
75 {
76 set = rb_malloc(sizeof(struct PrivilegeSet));
77 set->status = 0;
78 set->refs = 0;
79 set->name = rb_strdup(name);
80
81 rb_dlinkAdd(set, &set->node, &privilegeset_list);
82 }
83 set->privs = rb_strdup(privs);
84 set->flags = flags;
85
86 return set;
87 }
88
89 struct PrivilegeSet *
90 privilegeset_extend(struct PrivilegeSet *parent, const char *name, const char *privs, PrivilegeFlags flags)
91 {
92 struct PrivilegeSet *set;
93
94 s_assert(parent != NULL);
95 s_assert(name != NULL);
96 s_assert(privs != NULL);
97
98 set = privilegeset_get_any(name);
99 if (set != NULL)
100 {
101 if (!(set->status & CONF_ILLEGAL))
102 ilog(L_MAIN, "Duplicate privset %s", name);
103 set->status &= ~CONF_ILLEGAL;
104 rb_free(set->privs);
105 }
106 else
107 {
108 set = rb_malloc(sizeof(struct PrivilegeSet));
109 set->status = 0;
110 set->refs = 0;
111 set->name = rb_strdup(name);
112
113 rb_dlinkAdd(set, &set->node, &privilegeset_list);
114 }
115 set->flags = flags;
116 set->privs = rb_malloc(strlen(parent->privs) + 1 + strlen(privs) + 1);
117 strcpy(set->privs, parent->privs);
118 strcat(set->privs, " ");
119 strcat(set->privs, privs);
120
121 return set;
122 }
123
124 struct PrivilegeSet *
125 privilegeset_get(const char *name)
126 {
127 struct PrivilegeSet *set;
128
129 set = privilegeset_get_any(name);
130 if (set != NULL && set->status & CONF_ILLEGAL)
131 set = NULL;
132 return set;
133 }
134
135 struct PrivilegeSet *
136 privilegeset_ref(struct PrivilegeSet *set)
137 {
138 s_assert(set != NULL);
139
140 set->refs++;
141
142 return set;
143 }
144
145 void
146 privilegeset_unref(struct PrivilegeSet *set)
147 {
148 s_assert(set != NULL);
149
150 if (set->refs > 0)
151 set->refs--;
152 else
153 ilog(L_MAIN, "refs on privset %s is already 0",
154 set->name);
155 if (set->refs == 0 && set->status & CONF_ILLEGAL)
156 {
157 rb_dlinkDelete(&set->node, &privilegeset_list);
158
159 rb_free(set->name);
160 rb_free(set->privs);
161 rb_free(set);
162 }
163 }
164
165 void
166 privilegeset_mark_all_illegal(void)
167 {
168 rb_dlink_node *iter;
169
170 RB_DLINK_FOREACH(iter, privilegeset_list.head)
171 {
172 struct PrivilegeSet *set = (struct PrivilegeSet *) iter->data;
173
174 /* the "default" privset is special and must remain available */
175 if (!strcmp(set->name, "default"))
176 continue;
177
178 set->status |= CONF_ILLEGAL;
179 rb_free(set->privs);
180 set->privs = rb_strdup("");
181 /* but do not free it yet */
182 }
183 }
184
185 void
186 privilegeset_delete_all_illegal(void)
187 {
188 rb_dlink_node *iter, *next;
189
190 RB_DLINK_FOREACH_SAFE(iter, next, privilegeset_list.head)
191 {
192 struct PrivilegeSet *set = (struct PrivilegeSet *) iter->data;
193
194 privilegeset_ref(set);
195 privilegeset_unref(set);
196 }
197 }
198
199 void
200 privilegeset_report(struct Client *source_p)
201 {
202 rb_dlink_node *ptr;
203
204 RB_DLINK_FOREACH(ptr, privilegeset_list.head)
205 {
206 struct PrivilegeSet *set = ptr->data;
207
208 /* use RPL_STATSDEBUG for now -- jilles */
209 sendto_one_numeric(source_p, RPL_STATSDEBUG,
210 "O :%s %s",
211 set->name,
212 set->privs);
213 }
214 }