ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/conf/operator.c
Revision: 721
Committed: Sun Jul 16 17:02:55 2006 UTC (20 years ago) by adx
Content type: text/x-csrc
File size: 10548 byte(s)
Log Message:
+ added missing class unreference when multiple "class=" lines were
  encountered.

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * operator.c: Defines the operator{} block of ircd.conf.
4 *
5 * Copyright (C) 2006 by the Hybrid Development Team.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "conf/conf.h"
27 #include "ircd_defs.h"
28 #include "client.h"
29 #include "numeric.h"
30 #include "send.h"
31
32 dlink_list oper_confs = {NULL, NULL, 0};
33
34 static dlink_node *hreset;
35 static struct OperatorConf tmpoper = {0};
36
37 static const struct FlagMapping {
38 char letter;
39 const char *name;
40 unsigned int flag;
41 } flag_mappings[] = {
42 {'A', "admin", OPER_FLAG_ADMIN},
43 {'B', "remoteban", OPER_FLAG_REMOTEBAN},
44 {'D', "die", OPER_FLAG_DIE},
45 {'G', "gline", OPER_FLAG_GLINE},
46 {'H', "rehash", OPER_FLAG_REHASH},
47 {'K', "kline", OPER_FLAG_K},
48 {'L', "operwall", OPER_FLAG_OPERWALL},
49 {'N', "nick_changes", OPER_FLAG_N},
50 {'O', "global_kill", OPER_FLAG_GLOBAL_KILL},
51 {'R', "remote", OPER_FLAG_REMOTE},
52 {'U', "unkline", OPER_FLAG_UNKLINE},
53 {'X', "xline", OPER_FLAG_X},
54 {0, "hidden_admin", OPER_FLAG_HIDDEN_ADMIN},
55 {0, "hidden_oper", OPER_FLAG_HIDDEN_OPER},
56 {0, NULL, 0}
57 };
58
59 /*
60 * oper_privs_as_string()
61 *
62 * Translates an integer flags value to a string representation.
63 *
64 * inputs: flags
65 * output: static string
66 */
67 char *
68 oper_privs_as_string(int flags)
69 {
70 const struct FlagMapping *m;
71 static char str[32];
72 char *p = str;
73
74 for (m = flag_mappings; m->letter; m++)
75 if ((flags & m->flag) != 0)
76 *p++ = m->letter;
77 else
78 *p++ = tolower(m->letter);
79
80 *p = 0;
81 return str;
82 }
83
84 /*
85 * conf_operator_report()
86 *
87 * Reports all OperatorConf blocks along with their mask lists.
88 *
89 * inputs: a client to send to
90 * output: none
91 */
92 void
93 conf_operator_report(struct Client *source_p)
94 {
95 dlink_node *ptr = NULL;
96
97 DLINK_FOREACH(ptr, oper_confs.head)
98 {
99 dlink_node *ptr_mask = NULL;
100 struct OperatorConf *conf = ptr->data;
101
102 assert(conf->class_ptr);
103
104 DLINK_FOREACH(ptr_mask, conf->masks.head)
105 {
106 const struct split_nuh_item *nuh = ptr_mask->data;
107
108 // Don't allow non opers to see oper privs
109 sendto_one(source_p, form_str(RPL_STATSOLINE), me.name, source_p->name,
110 'O', nuh->userptr, nuh->hostptr, conf->name,
111 IsOper(source_p) ? oper_privs_as_string(conf->flags) : "0",
112 conf->class_ptr->name);
113 }
114 }
115 }
116
117 /*
118 * clear_operconf()
119 *
120 * Frees all memory used by fields of a OperatorConf struct.
121 *
122 * inputs: pointer to operconf
123 * output: none
124 */
125 static void
126 clear_operconf(struct OperatorConf *conf)
127 {
128 dlink_node *ptr, *ptr_next;
129
130 MyFree(conf->name);
131 MyFree(conf->passwd);
132 conf->name = conf->passwd = NULL;
133
134 DLINK_FOREACH_SAFE(ptr, ptr_next, conf->masks.head)
135 {
136 struct split_nuh_item *mask = ptr->data;
137
138 dlinkDelete(ptr, &conf->masks);
139
140 MyFree(mask->userptr);
141 MyFree(mask->hostptr);
142 MyFree(mask);
143 }
144
145 unref_class(conf->class_ptr);
146 conf->class_ptr = NULL;
147
148 #ifdef HAVE_LIBCRYPTO
149 if (conf->rsa_public_key != NULL)
150 {
151 RSA_free(conf->rsa_public_key);
152 conf->rsa_public_key = NULL;
153 }
154 #endif
155 }
156
157 /*
158 * find_operconf()
159 *
160 * Looks for a OperatorConf struct matching given parameters.
161 *
162 * inputs:
163 * name - operator name
164 * user - username to match, can be NULL
165 * host - hostname to match, can be NULL
166 * ip - IP address to match, can be NULL
167 * output: pointer to struct OperatorConf or NULL
168 */
169 struct OperatorConf *
170 find_operconf(const char *name, const char *user, const char *host,
171 const struct irc_ssaddr *ip)
172 {
173 dlink_node *ptr, *ptr_mask;
174 struct OperatorConf *conf;
175 struct irc_ssaddr ipmask;
176 int mbits;
177
178 DLINK_FOREACH(ptr, oper_confs.head)
179 {
180 conf = ptr->data;
181 if (irccmp(conf->name, name))
182 continue;
183
184 DLINK_FOREACH(ptr_mask, conf->masks.head)
185 {
186 struct split_nuh_item *uh = ptr_mask->data;
187
188 if (user && !match(uh->userptr, user))
189 continue;
190
191 if (host != NULL || ip != NULL)
192 {
193 /* We get here once or twice per find_operconf() call,
194 * so we can afford this. -- adx
195 */
196 switch (parse_netmask(uh->hostptr, &ipmask, &mbits))
197 {
198 case HM_IPV4: if (!ip || !match_ipv4(ip, &ipmask, mbits))
199 continue;
200 #ifdef IPV6
201 case HM_IPV6: if (!ip || !match_ipv6(ip, &ipmask, mbits))
202 continue;
203 #endif
204 default: if (!host || !match(uh->hostptr, host))
205 continue;
206 }
207 }
208
209 return conf;
210 }
211 }
212
213 return NULL;
214 }
215
216 /*
217 * reset_operator()
218 *
219 * Frees all operator{} blocks. Called on a rehash.
220 *
221 * inputs: none
222 * output: none
223 */
224 static void *
225 reset_operator(va_list args)
226 {
227 struct OperatorConf *conf;
228
229 while (oper_confs.head != NULL)
230 {
231 conf = oper_confs.head->data;
232 dlinkDelete(&conf->node, &oper_confs);
233 clear_operconf(conf);
234 MyFree(conf);
235 }
236
237 return pass_callback(hreset);
238 }
239
240 /*
241 * before_operator()
242 *
243 * Called before processing a single operator{} block.
244 *
245 * inputs: none
246 * output: none
247 */
248 static void
249 before_operator(void)
250 {
251 clear_operconf(&tmpoper);
252 tmpoper.flags |= OPER_FLAG_ENCRYPTED;
253 }
254
255 /*
256 * after_operator()
257 *
258 * Called after parsing a single operator{} block.
259 *
260 * inputs: none
261 * output: none
262 */
263 static void
264 after_operator(void)
265 {
266 struct OperatorConf *oper;
267
268 if (tmpoper.class_ptr == NULL)
269 {
270 parse_error("Invalid or non-existant class in operator{}");
271 clear_operconf(&tmpoper);
272 return;
273 }
274
275 if (tmpoper.name == NULL || dlink_list_length(&tmpoper.masks) == 0 ||
276 #ifdef HAVE_LIBCRYPTO
277 !tmpoper.passwd
278 #else
279 (!tmpoper.passwd && !tmpoper.rsa_public_key)
280 #endif
281 )
282 {
283 parse_error("Incomplete operator{} block");
284 clear_operconf(&tmpoper);
285 return;
286 }
287
288 oper = MyMalloc(sizeof(struct OperatorConf));
289
290 memcpy(oper, &tmpoper, sizeof(*oper));
291 memset(&tmpoper, 0, sizeof(tmpoper));
292
293 dlinkAddTail(oper, &oper->node, &oper_confs);
294 }
295
296 /*
297 * oper_encrypted()
298 *
299 * Parses the "encrypted=" directive.
300 *
301 * inputs: binary value (given as a pointer)
302 * output: none
303 */
304 static void
305 oper_encrypted(void *value, void *where)
306 {
307 if (*(int *) value)
308 tmpoper.flags |= OPER_FLAG_ENCRYPTED;
309 else
310 tmpoper.flags &= ~OPER_FLAG_ENCRYPTED;
311 }
312
313 /*
314 * oper_user()
315 *
316 * Parses the "user=" directive.
317 *
318 * inputs: new user@host mask
319 * output: none
320 */
321 static void
322 oper_user(void *value, void *where)
323 {
324 char *str = value;
325 char userbuf[USERLEN + 1];
326 char hostbuf[HOSTLEN + 1];
327 struct split_nuh_item nuh, *cuh;
328
329 nuh.nuhmask = str;
330 nuh.nickptr = NULL;
331 nuh.userptr = userbuf;
332 nuh.hostptr = hostbuf;
333
334 nuh.nicksize = 0;
335 nuh.usersize = sizeof(userbuf);
336 nuh.hostsize = sizeof(hostbuf);
337
338 split_nuh(&nuh);
339
340 cuh = MyMalloc(sizeof(*cuh));
341 DupString(cuh->userptr, nuh.userptr);
342 DupString(cuh->hostptr, nuh.hostptr);
343
344 dlinkAdd(cuh, &cuh->node, &tmpoper.masks);
345 }
346
347 /*
348 * oper_class()
349 *
350 * Parses the "class=" directive.
351 *
352 * inputs: class name pointer
353 * output: none
354 */
355 static void
356 oper_class(void *value, void *where)
357 {
358 if (tmpoper.class_ptr != NULL)
359 unref_class(tmpoper.class_ptr);
360
361 tmpoper.class_ptr = ref_class_by_name(value);
362 }
363
364 /*
365 * oper_rsa_public_key_file()
366 *
367 * Parses the "rsa_public_key_file=" directive.
368 *
369 * inputs: file name pointer
370 * output: none
371 */
372 static void
373 oper_rsa_public_key_file(void *value, void *where)
374 {
375 #ifndef HAVE_LIBCRYPTO
376 parse_error("Ignoring rsa_public_key_file -- no OpenSSL support.");
377 #else
378 const char *str = value;
379 BIO *file = NULL;
380
381 if (tmpoper.rsa_public_key != NULL)
382 {
383 RSA_free(tmpoper.rsa_public_key);
384 tmpoper.rsa_public_key = NULL;
385 }
386
387 if ((file = BIO_new_file(str, "r")) == NULL)
388 {
389 parse_error("Ignoring rsa_public_key_file -- file doesn't exist");
390 return;
391 }
392
393 tmpoper.rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL);
394 if (tmpoper.rsa_public_key == NULL)
395 parse_error("Ignoring rsa_public_key_file -- Key invalid; check key syntax.");
396
397 BIO_set_close(file, BIO_CLOSE);
398 BIO_free(file);
399 #endif
400 }
401
402 /*
403 * parse_flag_list()
404 *
405 * Parses a list of oper flags
406 *
407 * inputs:
408 * list - points to a dlink_list of strings to parse
409 * var - where to save the result as unsigned int
410 * output: none
411 */
412 static void
413 parse_flag_list(void *list, void *where)
414 {
415 const struct FlagMapping *p;
416 int errors = NO;
417 dlink_node *ptr;
418
419 tmpoper.flags &= OPER_FLAG_ENCRYPTED;
420
421 DLINK_FOREACH(ptr, ((dlink_list *)list)->head)
422 {
423 const char *str = ptr->data;
424 int found = NO, all = !irccmp(str, "all");
425
426 for (p = flag_mappings; p->name; ++p)
427 if (all || !irccmp(str, p->name))
428 {
429 found = YES;
430 if (!all || p->letter)
431 tmpoper.flags |= p->flag;
432 if (!all || !p->letter)
433 break;
434 }
435
436 if (!found)
437 errors = YES;
438 }
439
440 if (errors)
441 parse_error("Invalid oper flags encountered, check your syntax");
442 }
443
444 /*
445 * init_operator()
446 *
447 * Initializes oper{} block support.
448 *
449 * inputs: none
450 * output: none
451 */
452 void
453 init_operator(void)
454 {
455 const char *alias[] = { "oper", "operator", NULL };
456 const char **p = alias;
457
458 hreset = install_hook(reset_conf, reset_operator);
459
460 for (; *p != NULL; ++p)
461 {
462 struct ConfSection *s = add_conf_section(*p, 2);
463
464 s->before = before_operator;
465
466 s->def_field = add_conf_field(s, "name", CT_STRING, NULL, &tmpoper.name);
467 add_conf_field(s, "user", CT_STRING, oper_user, NULL);
468 add_conf_field(s, "class", CT_STRING, oper_class, NULL);
469 add_conf_field(s, "password", CT_STRING, NULL, &tmpoper.passwd);
470 add_conf_field(s, "encrypted", CT_BOOL, oper_encrypted, NULL);
471 add_conf_field(s, "rsa_public_keyfile", CT_STRING, oper_rsa_public_key_file, NULL);
472 add_conf_field(s, "flags", CT_LIST, parse_flag_list, NULL);
473
474 s->after = after_operator;
475 }
476 }

Properties

Name Value
svn:eol-style native
svn:keywords "Id Revision"