]> jfr.im git - solanum.git/blame - ircd/capability.c
chmode: Get elevated access for op-only queries
[solanum.git] / ircd / capability.c
CommitLineData
64b56afd
AC
1/*
2 * Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
7 *
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
19 */
20
21#include "stdinc.h"
22#include "capability.h"
a4bf26dd 23#include "rb_dictionary.h"
77d3d2db 24#include "s_assert.h"
64b56afd 25
885cd603
AC
26static rb_dlink_list capability_indexes = { NULL, NULL, 0 };
27
32df5e96
AC
28struct CapabilityEntry *
29capability_find(struct CapabilityIndex *idx, const char *cap)
30{
31 s_assert(idx != NULL);
32 if (cap == NULL)
33 return NULL;
34
a4bf26dd 35 return rb_dictionary_retrieve(idx->cap_dict, cap);
32df5e96
AC
36}
37
64b56afd 38unsigned int
63b9db96 39capability_get(struct CapabilityIndex *idx, const char *cap, void **ownerdata)
64b56afd
AC
40{
41 struct CapabilityEntry *entry;
42
bde42c60 43 s_assert(idx != NULL);
d7e4ed77
AC
44 if (cap == NULL)
45 return 0;
64b56afd 46
a4bf26dd 47 entry = rb_dictionary_retrieve(idx->cap_dict, cap);
5058c8eb 48 if (entry != NULL && !(entry->flags & CAP_ORPHANED))
63b9db96
AC
49 {
50 if (ownerdata != NULL)
51 *ownerdata = entry->ownerdata;
8bedf01d 52 return (1 << entry->value);
63b9db96 53 }
64b56afd 54
8d20b088 55 return 0;
64b56afd
AC
56}
57
58unsigned int
63b9db96 59capability_put(struct CapabilityIndex *idx, const char *cap, void *ownerdata)
64b56afd
AC
60{
61 struct CapabilityEntry *entry;
62
bde42c60
JT
63 s_assert(idx != NULL);
64 if (!idx->highest_bit)
8bedf01d 65 return 0xFFFFFFFF;
64b56afd 66
a4bf26dd 67 if ((entry = rb_dictionary_retrieve(idx->cap_dict, cap)) != NULL)
64b56afd 68 {
5058c8eb 69 entry->flags &= ~CAP_ORPHANED;
1e221ac3
EK
70 if (ownerdata != NULL)
71 {
72 s_assert(entry->ownerdata == NULL);
73 entry->ownerdata = ownerdata;
74 }
8bedf01d 75 return (1 << entry->value);
64b56afd
AC
76 }
77
78 entry = rb_malloc(sizeof(struct CapabilityEntry));
94afbe9c 79 entry->cap = rb_strdup(cap);
5058c8eb 80 entry->flags = 0;
bde42c60 81 entry->value = idx->highest_bit;
63b9db96 82 entry->ownerdata = ownerdata;
64b56afd 83
a4bf26dd 84 rb_dictionary_add(idx->cap_dict, entry->cap, entry);
64b56afd 85
bde42c60
JT
86 idx->highest_bit++;
87 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
88 idx->highest_bit = 0;
64b56afd 89
8bedf01d 90 return (1 << entry->value);
64b56afd
AC
91}
92
22cae20f
JT
93unsigned int
94capability_put_anonymous(struct CapabilityIndex *idx)
95{
96 unsigned int value;
97
98 s_assert(idx != NULL);
99 if (!idx->highest_bit)
100 return 0xFFFFFFFF;
101 value = 1 << idx->highest_bit;
102 idx->highest_bit++;
103 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
104 idx->highest_bit = 0;
105 return value;
106}
107
64b56afd 108void
bde42c60 109capability_orphan(struct CapabilityIndex *idx, const char *cap)
64b56afd
AC
110{
111 struct CapabilityEntry *entry;
112
bde42c60 113 s_assert(idx != NULL);
64b56afd 114
a4bf26dd 115 entry = rb_dictionary_retrieve(idx->cap_dict, cap);
64b56afd 116 if (entry != NULL)
f01f67f0
AC
117 {
118 entry->flags &= ~CAP_REQUIRED;
5058c8eb 119 entry->flags |= CAP_ORPHANED;
2e4bf32f 120 entry->ownerdata = NULL;
f01f67f0
AC
121 }
122}
123
124void
bde42c60 125capability_require(struct CapabilityIndex *idx, const char *cap)
f01f67f0
AC
126{
127 struct CapabilityEntry *entry;
128
bde42c60 129 s_assert(idx != NULL);
f01f67f0 130
a4bf26dd 131 entry = rb_dictionary_retrieve(idx->cap_dict, cap);
f01f67f0
AC
132 if (entry != NULL)
133 entry->flags |= CAP_REQUIRED;
64b56afd
AC
134}
135
136static void
4177311e 137capability_destroy(rb_dictionary_element *delem, void *privdata)
64b56afd
AC
138{
139 s_assert(delem != NULL);
140
94afbe9c
JV
141 struct CapabilityEntry *entry = delem->data;
142 rb_free((char *)entry->cap);
143 rb_free(entry);
64b56afd
AC
144}
145
146struct CapabilityIndex *
885cd603 147capability_index_create(const char *name)
64b56afd 148{
bde42c60 149 struct CapabilityIndex *idx;
64b56afd 150
bde42c60 151 idx = rb_malloc(sizeof(struct CapabilityIndex));
ba832267 152 idx->name = name;
f956cb0f 153 idx->cap_dict = rb_dictionary_create(name, rb_strcasecmp);
bde42c60 154 idx->highest_bit = 1;
64b56afd 155
885cd603
AC
156 rb_dlinkAdd(idx, &idx->node, &capability_indexes);
157
bde42c60 158 return idx;
64b56afd
AC
159}
160
161void
bde42c60 162capability_index_destroy(struct CapabilityIndex *idx)
64b56afd 163{
bde42c60 164 s_assert(idx != NULL);
64b56afd 165
885cd603
AC
166 rb_dlinkDelete(&idx->node, &capability_indexes);
167
a4bf26dd 168 rb_dictionary_destroy(idx->cap_dict, capability_destroy, NULL);
bde42c60 169 rb_free(idx);
64b56afd 170}
5e773521
AC
171
172const char *
bde42c60 173capability_index_list(struct CapabilityIndex *idx, unsigned int cap_mask)
5e773521 174{
4177311e 175 rb_dictionary_iter iter;
5e773521
AC
176 struct CapabilityEntry *entry;
177 static char buf[BUFSIZE];
178 char *t = buf;
179 int tl;
180
bde42c60 181 s_assert(idx != NULL);
5e773521
AC
182
183 *t = '\0';
184
56f84ded 185 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
5e773521 186 {
33b214fa 187 if ((1 << entry->value) & cap_mask)
5e773521 188 {
5203cba5 189 tl = sprintf(t, "%s ", entry->cap);
5e773521
AC
190 t += tl;
191 }
192 }
193
194 t--;
195 *t = '\0';
196
197 return buf;
198}
ec3a9055
AC
199
200unsigned int
bde42c60 201capability_index_mask(struct CapabilityIndex *idx)
ec3a9055 202{
4177311e 203 rb_dictionary_iter iter;
ec3a9055
AC
204 struct CapabilityEntry *entry;
205 unsigned int mask = 0;
206
bde42c60 207 s_assert(idx != NULL);
ec3a9055 208
56f84ded 209 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
ec3a9055 210 {
0582290f 211 if (!(entry->flags & CAP_ORPHANED))
8bedf01d 212 mask |= (1 << entry->value);
ec3a9055
AC
213 }
214
215 return mask;
216}
f01f67f0
AC
217
218unsigned int
bde42c60 219capability_index_get_required(struct CapabilityIndex *idx)
f01f67f0 220{
4177311e 221 rb_dictionary_iter iter;
f01f67f0
AC
222 struct CapabilityEntry *entry;
223 unsigned int mask = 0;
224
bde42c60 225 s_assert(idx != NULL);
f01f67f0 226
56f84ded 227 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
f01f67f0
AC
228 {
229 if (!(entry->flags & CAP_ORPHANED) && (entry->flags & CAP_REQUIRED))
8bedf01d 230 mask |= (1 << entry->value);
f01f67f0
AC
231 }
232
233 return mask;
234}
a16910aa
AC
235
236void
237capability_index_stats(void (*cb)(const char *line, void *privdata), void *privdata)
238{
239 rb_dlink_node *node;
240 char buf[BUFSIZE];
241
242 RB_DLINK_FOREACH(node, capability_indexes.head)
243 {
244 struct CapabilityIndex *idx = node->data;
4177311e 245 rb_dictionary_iter iter;
a16910aa
AC
246 struct CapabilityEntry *entry;
247
5203cba5 248 snprintf(buf, sizeof buf, "'%s': allocated bits - %d", idx->name, (idx->highest_bit - 1));
a16910aa
AC
249 cb(buf, privdata);
250
56f84ded 251 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
a16910aa 252 {
5203cba5 253 snprintf(buf, sizeof buf, "bit %d: '%s'", entry->value, entry->cap);
a16910aa
AC
254 cb(buf, privdata);
255 }
256
5203cba5 257 snprintf(buf, sizeof buf, "'%s': remaining bits - %u", idx->name,
0c5e50f4 258 (unsigned int)((sizeof(unsigned int) * 8) - (idx->highest_bit - 1)));
a16910aa
AC
259 cb(buf, privdata);
260 }
261
5203cba5 262 snprintf(buf, sizeof buf, "%ld capability indexes", rb_dlink_list_length(&capability_indexes));
a16910aa
AC
263 cb(buf, privdata);
264}