ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/conf/operator.c
Revision: 722
Committed: Sun Jul 16 17:10:00 2006 UTC (20 years ago) by adx
Content type: text/x-csrc
File size: 10552 byte(s)
Log Message:
+ save user= entries in the order they're entered

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 michael 417
32 adx 719 dlink_list oper_confs = {NULL, NULL, 0};
33 michael 476
34 adx 719 static dlink_node *hreset;
35     static struct OperatorConf tmpoper = {0};
36 michael 476
37 michael 417 static const struct FlagMapping {
38 adx 719 char letter;
39 michael 417 const char *name;
40 michael 476 unsigned int flag;
41 michael 417 } flag_mappings[] = {
42 adx 719 {'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 michael 417 };
58    
59 adx 719 /*
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 michael 422 void
93     conf_operator_report(struct Client *source_p)
94     {
95     dlink_node *ptr = NULL;
96    
97 adx 719 DLINK_FOREACH(ptr, oper_confs.head)
98 michael 422 {
99     dlink_node *ptr_mask = NULL;
100 adx 719 struct OperatorConf *conf = ptr->data;
101 michael 422
102 adx 719 assert(conf->class_ptr);
103    
104     DLINK_FOREACH(ptr_mask, conf->masks.head)
105 michael 422 {
106     const struct split_nuh_item *nuh = ptr_mask->data;
107    
108 adx 719 // 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 michael 422 }
114     }
115     }
116    
117 adx 719 /*
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 michael 417 static void
126 adx 719 clear_operconf(struct OperatorConf *conf)
127 michael 418 {
128 adx 719 dlink_node *ptr, *ptr_next;
129 michael 418
130 adx 719 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 michael 418 }
156    
157 adx 719 /*
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 michael 418 static void
249 michael 417 before_operator(void)
250     {
251 adx 719 clear_operconf(&tmpoper);
252     tmpoper.flags |= OPER_FLAG_ENCRYPTED;
253 michael 417 }
254    
255 adx 719 /*
256     * after_operator()
257     *
258     * Called after parsing a single operator{} block.
259     *
260     * inputs: none
261     * output: none
262     */
263 michael 417 static void
264     after_operator(void)
265     {
266 adx 719 struct OperatorConf *oper;
267 michael 417
268 adx 719 if (tmpoper.class_ptr == NULL)
269 michael 418 {
270     parse_error("Invalid or non-existant class in operator{}");
271 adx 719 clear_operconf(&tmpoper);
272 michael 417 return;
273 michael 418 }
274 michael 417
275 adx 719 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 michael 418 return;
286 adx 719 }
287 michael 417
288 adx 719 oper = MyMalloc(sizeof(struct OperatorConf));
289 michael 417
290 adx 719 memcpy(oper, &tmpoper, sizeof(*oper));
291     memset(&tmpoper, 0, sizeof(tmpoper));
292 michael 417
293 adx 719 dlinkAddTail(oper, &oper->node, &oper_confs);
294 michael 417 }
295    
296 adx 719 /*
297     * oper_encrypted()
298     *
299     * Parses the "encrypted=" directive.
300     *
301     * inputs: binary value (given as a pointer)
302     * output: none
303     */
304 michael 417 static void
305     oper_encrypted(void *value, void *where)
306     {
307 adx 719 if (*(int *) value)
308     tmpoper.flags |= OPER_FLAG_ENCRYPTED;
309 michael 417 else
310 adx 719 tmpoper.flags &= ~OPER_FLAG_ENCRYPTED;
311 michael 417 }
312    
313 adx 719 /*
314     * oper_user()
315     *
316     * Parses the "user=" directive.
317     *
318     * inputs: new user@host mask
319     * output: none
320     */
321 michael 417 static void
322 michael 476 oper_user(void *value, void *where)
323 michael 417 {
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 adx 722 dlinkAddTail(cuh, &cuh->node, &tmpoper.masks);
345 michael 417 }
346    
347 adx 719 /*
348     * oper_class()
349     *
350     * Parses the "class=" directive.
351     *
352     * inputs: class name pointer
353     * output: none
354     */
355 michael 417 static void
356 michael 476 oper_class(void *value, void *where)
357 michael 417 {
358 adx 721 if (tmpoper.class_ptr != NULL)
359     unref_class(tmpoper.class_ptr);
360    
361 adx 719 tmpoper.class_ptr = ref_class_by_name(value);
362 michael 417 }
363    
364 adx 719 /*
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 michael 417 static void
373     oper_rsa_public_key_file(void *value, void *where)
374     {
375 adx 719 #ifndef HAVE_LIBCRYPTO
376     parse_error("Ignoring rsa_public_key_file -- no OpenSSL support.");
377     #else
378 michael 417 const char *str = value;
379     BIO *file = NULL;
380    
381 adx 719 if (tmpoper.rsa_public_key != NULL)
382 michael 417 {
383 adx 719 RSA_free(tmpoper.rsa_public_key);
384     tmpoper.rsa_public_key = NULL;
385 michael 417 }
386    
387 adx 719 if ((file = BIO_new_file(str, "r")) == NULL)
388 michael 417 {
389 michael 418 parse_error("Ignoring rsa_public_key_file -- file doesn't exist");
390 michael 417 return;
391     }
392    
393 adx 719 tmpoper.rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL);
394     if (tmpoper.rsa_public_key == NULL)
395 michael 418 parse_error("Ignoring rsa_public_key_file -- Key invalid; check key syntax.");
396 michael 417
397     BIO_set_close(file, BIO_CLOSE);
398     BIO_free(file);
399 adx 719 #endif
400 michael 417 }
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 adx 719 const struct FlagMapping *p;
416     int errors = NO;
417 michael 417 dlink_node *ptr;
418    
419 adx 719 tmpoper.flags &= OPER_FLAG_ENCRYPTED;
420    
421 michael 417 DLINK_FOREACH(ptr, ((dlink_list *)list)->head)
422     {
423     const char *str = ptr->data;
424 adx 719 int found = NO, all = !irccmp(str, "all");
425 michael 417
426 michael 476 for (p = flag_mappings; p->name; ++p)
427 adx 719 if (all || !irccmp(str, p->name))
428 michael 417 {
429     found = YES;
430 adx 719 if (!all || p->letter)
431     tmpoper.flags |= p->flag;
432     if (!all || !p->letter)
433     break;
434 michael 417 }
435    
436     if (!found)
437 adx 719 errors = YES;
438 michael 417 }
439    
440 adx 719 if (errors)
441     parse_error("Invalid oper flags encountered, check your syntax");
442 michael 417 }
443    
444 adx 719 /*
445     * init_operator()
446     *
447     * Initializes oper{} block support.
448     *
449     * inputs: none
450     * output: none
451     */
452 michael 417 void
453     init_operator(void)
454     {
455 michael 419 const char *alias[] = { "oper", "operator", NULL };
456 adx 719 const char **p = alias;
457 michael 417
458 michael 418 hreset = install_hook(reset_conf, reset_operator);
459 michael 417
460 adx 719 for (; *p != NULL; ++p)
461 michael 419 {
462 adx 719 struct ConfSection *s = add_conf_section(*p, 2);
463 michael 417
464 michael 419 s->before = before_operator;
465 michael 417
466 adx 423 s->def_field = add_conf_field(s, "name", CT_STRING, NULL, &tmpoper.name);
467 michael 419 add_conf_field(s, "user", CT_STRING, oper_user, NULL);
468     add_conf_field(s, "class", CT_STRING, oper_class, NULL);
469 adx 719 add_conf_field(s, "password", CT_STRING, NULL, &tmpoper.passwd);
470 michael 419 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 michael 417
474 michael 419 s->after = after_operator;
475     }
476 michael 417 }

Properties

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