ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/conf/operator.c
Revision: 749
Committed: Tue Jul 25 19:45:47 2006 UTC (20 years ago) by adx
Content type: text/x-csrc
File size: 11383 byte(s)
Log Message:
+ make everything compile, but not yet link

File Contents

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

Properties

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