]> jfr.im git - irc/rqf/shadowircd.git/blob - tools/convertilines.c
Add operspy /topic.
[irc/rqf/shadowircd.git] / tools / convertilines.c
1 /* tools/convertilines.c
2 * Copyright (c) 2002 Hybrid Development Team
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * 1.Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2.Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3.The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $Id: convertilines.c 6 2005-09-10 01:02:21Z nenolod $
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #include <string.h>
35
36 #define BUFSIZE 512
37
38 #define FLAGS_RESTRICTED 0x001
39 #define FLAGS_EXCEEDLIMIT 0x002
40 #define FLAGS_KLINEEXEMPT 0x004
41 #define FLAGS_NEEDIDENT 0x010
42 #define FLAGS_NOTILDE 0x020
43
44 struct flag_table_struct
45 {
46 const char *name;
47 int flag;
48 };
49 static struct flag_table_struct flag_table[] =
50 {
51 { "restricted", FLAGS_RESTRICTED },
52 { "exceed_limit", FLAGS_EXCEEDLIMIT },
53 { "kline_exempt", FLAGS_KLINEEXEMPT },
54 { "need_ident", FLAGS_NEEDIDENT },
55 { "no_tilde", FLAGS_NOTILDE },
56 { NULL, 0 }
57 };
58
59 struct AuthBlock
60 {
61 struct AuthBlock *next;
62
63 char **hostname;
64 int hostnum;
65
66 char *spoof;
67 char *passwd;
68 int class;
69 int flags;
70
71 /* indicates one of above */
72 int special;
73 int specialk;
74 };
75
76 static struct AuthBlock *auth_spoof = NULL;
77 static struct AuthBlock *auth_special = NULL;
78 static struct AuthBlock *auth_passwd = NULL;
79 static struct AuthBlock *auth_general = NULL;
80 static struct AuthBlock *auth_restricted = NULL;
81
82 static void ConvertConf(FILE* file,FILE *out);
83 static void set_flags(struct AuthBlock *, const char *, const char *);
84 static void usage(void);
85 static char *getfield(char *);
86 static struct AuthBlock *find_matching_conf(struct AuthBlock *);
87 static void ReplaceQuotes(char *out, char *in);
88 static void oldParseOneLine(FILE *out, char *in);
89 static void write_auth_entries(FILE *out);
90 static void write_specific(FILE *out, struct AuthBlock *);
91 static int match(struct AuthBlock *, struct AuthBlock *);
92
93 int main(int argc,char *argv[])
94 {
95 FILE *in;
96 FILE *out;
97
98 if(argc < 3)
99 usage();
100
101 if((in = fopen(argv[1],"r")) == NULL)
102 {
103 fprintf(stderr, "Can't open %s for reading\n", argv[1]);
104 usage();
105 }
106
107 if((out = fopen(argv[2],"w")) == NULL)
108 {
109 fprintf(stderr, "Can't open %s for writing\n", argv[2]);
110 usage();
111 }
112
113 ConvertConf(in, out);
114
115 return 0;
116 }
117
118 void usage()
119 {
120 fprintf(stderr, "convertilines conf.old conf.new\n");
121 exit(-1);
122 }
123
124 /*
125 * ConvertConf()
126 * Read configuration file.
127 *
128 *
129 * Inputs - FILE* to config file to convert
130 * - FILE* to output for new style conf
131 *
132 */
133
134 #define MAXCONFLINKS 150
135
136 static void ConvertConf(FILE* file, FILE *out)
137 {
138 char line[BUFSIZE];
139 char quotedLine[BUFSIZE];
140 char* p;
141
142 while (fgets(line, sizeof(line), file))
143 {
144 if ((p = strchr(line, '\n')))
145 *p = '\0';
146
147 ReplaceQuotes(quotedLine,line);
148
149 if(!*quotedLine || quotedLine[0] == '#' || quotedLine[0] == '\n' ||
150 quotedLine[0] == ' ' || quotedLine[0] == '\t')
151 continue;
152
153 if(quotedLine[0] == '.')
154 {
155 char *filename;
156 char *back;
157
158 if(!strncmp(quotedLine+1,"include ",8))
159 {
160 if( (filename = strchr(quotedLine+8,'"')) )
161 filename++;
162 else
163 {
164 fprintf(stderr, "Bad config line: %s", quotedLine);
165 continue;
166 }
167
168 if((back = strchr(filename,'"')))
169 *back = '\0';
170 else
171 {
172 fprintf(stderr, "Bad config line: %s", quotedLine);
173 continue;
174 }
175
176 }
177 }
178
179 /* Could we test if it's conf line at all? -Vesa */
180 if (quotedLine[1] == ':')
181 oldParseOneLine(out,quotedLine);
182
183 }
184
185 fclose(file);
186
187 write_auth_entries(out);
188 fclose(out);
189 }
190
191 /*
192 * ReplaceQuotes
193 * Inputs - input line to quote
194 * Output - quoted line
195 * Side Effects - All quoted chars in input are replaced
196 * with quoted values in output, # chars replaced with '\0'
197 * otherwise input is copied to output.
198 */
199 static void ReplaceQuotes(char* quotedLine,char *inputLine)
200 {
201 char *in;
202 char *out;
203 static char quotes[] = {
204 0, /* */
205 0, /* a */
206 '\b', /* b */
207 0, /* c */
208 0, /* d */
209 0, /* e */
210 '\f', /* f */
211 0, /* g */
212 0, /* h */
213 0, /* i */
214 0, /* j */
215 0, /* k */
216 0, /* l */
217 0, /* m */
218 '\n', /* n */
219 0, /* o */
220 0, /* p */
221 0, /* q */
222 '\r', /* r */
223 0, /* s */
224 '\t', /* t */
225 0, /* u */
226 '\v', /* v */
227 0, /* w */
228 0, /* x */
229 0, /* y */
230 0, /* z */
231 0,0,0,0,0,0
232 };
233
234 /*
235 * Do quoting of characters and # detection.
236 */
237 for (out = quotedLine,in = inputLine; *in; out++, in++)
238 {
239 if (*in == '\\')
240 {
241 in++;
242 if(*in == '\\')
243 *out = '\\';
244 else if(*in == '#')
245 *out = '#';
246 else
247 *out = quotes[ (unsigned int) (*in & 0x1F) ];
248 }
249 else if (*in == '#')
250 {
251 *out = '\0';
252 return;
253 }
254 else
255 *out = *in;
256 }
257 *out = '\0';
258 }
259
260 /*
261 * oldParseOneLine
262 * Inputs - pointer to line to parse
263 * - pointer to output to write
264 * Output -
265 * Side Effects - Parse one old style conf line.
266 */
267
268 static void oldParseOneLine(FILE *out,char* line)
269 {
270 char conf_letter;
271 char* tmp;
272 const char* host_field=NULL;
273 const char* passwd_field=NULL;
274 const char* user_field=NULL;
275 const char* port_field = NULL;
276 const char* classconf_field = NULL;
277 int class_field = 0;
278
279 tmp = getfield(line);
280
281 conf_letter = *tmp;
282
283 for (;;) /* Fake loop, that I can use break here --msa */
284 {
285 /* host field */
286 if ((host_field = getfield(NULL)) == NULL)
287 return;
288
289 /* pass field */
290 if ((passwd_field = getfield(NULL)) == NULL)
291 break;
292
293 /* user field */
294 if ((user_field = getfield(NULL)) == NULL)
295 break;
296
297 /* port field */
298 if ((port_field = getfield(NULL)) == NULL)
299 break;
300
301 /* class field */
302 if ((classconf_field = getfield(NULL)) == NULL)
303 break;
304
305 break;
306 }
307
308 if (!passwd_field)
309 passwd_field = "";
310 if (!user_field)
311 user_field = "";
312 if (!port_field)
313 port_field = "";
314 if (classconf_field)
315 class_field = atoi(classconf_field);
316
317 switch( conf_letter )
318 {
319 case 'i':
320 case 'I':
321 {
322 struct AuthBlock *ptr;
323 struct AuthBlock *tempptr;
324
325 tempptr = malloc(sizeof(struct AuthBlock));
326 memset(tempptr, 0, sizeof(*tempptr));
327
328 if(conf_letter == 'i')
329 {
330 tempptr->flags |= FLAGS_RESTRICTED;
331 tempptr->specialk = 1;
332 }
333
334 if(passwd_field && *passwd_field)
335 tempptr->passwd = strdup(passwd_field);
336
337 tempptr->class = class_field;
338
339 set_flags(tempptr, user_field, host_field);
340
341 /* dont add specials/passworded ones to existing auth blocks */
342 if((ptr = find_matching_conf(tempptr)))
343 {
344 int authindex;
345
346 authindex = ptr->hostnum;
347 ptr->hostnum++;
348
349 ptr->hostname = realloc((void *)ptr->hostname, ptr->hostnum * sizeof(void *));
350
351 ptr->hostname[authindex] = strdup(tempptr->hostname[0]);
352
353 free(tempptr->hostname[0]);
354 free(tempptr->hostname);
355 free(tempptr);
356 }
357 else
358 {
359 ptr = tempptr;
360
361 if(ptr->spoof)
362 {
363 ptr->next = auth_spoof;
364 auth_spoof = ptr;
365 }
366 else if(ptr->special)
367 {
368 ptr->next = auth_special;
369 auth_special = ptr;
370 }
371 else if(ptr->passwd)
372 {
373 ptr->next = auth_passwd;
374 auth_passwd = ptr;
375 }
376 else if(ptr->specialk)
377 {
378 ptr->next = auth_restricted;
379 auth_restricted = ptr;
380 }
381 else
382 {
383 ptr->next = auth_general;
384 auth_general = ptr;
385 }
386 }
387 }
388 break;
389
390 default:
391 break;
392 }
393 }
394
395 static void write_auth_entries(FILE *out)
396 {
397 struct AuthBlock *ptr;
398
399 for(ptr = auth_spoof; ptr; ptr = ptr->next)
400 write_specific(out, ptr);
401
402 for(ptr = auth_special; ptr; ptr = ptr->next)
403 write_specific(out, ptr);
404
405 for(ptr = auth_passwd; ptr; ptr = ptr->next)
406 write_specific(out, ptr);
407
408 for(ptr = auth_general; ptr; ptr = ptr->next)
409 write_specific(out, ptr);
410
411 for(ptr = auth_restricted; ptr; ptr = ptr->next)
412 write_specific(out, ptr);
413 }
414
415
416 static void write_specific(FILE *out, struct AuthBlock *ptr)
417 {
418 int i;
419 int prev = 0;
420
421 fprintf(out, "auth {\n");
422
423 for(i = 0; i < ptr->hostnum; i++)
424 fprintf(out, "\tuser = \"%s\";\n", ptr->hostname[i]);
425
426 if(ptr->spoof)
427 fprintf(out, "\tspoof = \"%s\";\n", ptr->spoof);
428
429 if(ptr->passwd)
430 fprintf(out, "\tpassword = \"%s\";\n", ptr->passwd);
431
432 if(ptr->flags)
433 {
434 fprintf(out, "\tflags = ");
435
436 for(i = 0; flag_table[i].flag; i++)
437 {
438 if(ptr->flags & flag_table[i].flag)
439 {
440 fprintf(out, "%s%s",
441 prev ? ", " : "",
442 flag_table[i].name);
443 prev = 1;
444 }
445 }
446
447 fprintf(out, ";\n");
448 }
449
450 fprintf(out, "\tclass = \"%d\";\n", ptr->class);
451 fprintf(out, "};\n");
452 }
453
454 /*
455 * field breakup for ircd.conf file.
456 */
457 static char *getfield(char *newline)
458 {
459 static char *line = NULL;
460 char *end, *field;
461
462 if (newline)
463 line = newline;
464
465 if (line == NULL)
466 return(NULL);
467
468 field = line;
469 if ((end = strchr(line,':')) == NULL)
470 {
471 line = NULL;
472 if ((end = strchr(field,'\n')) == NULL)
473 end = field + strlen(field);
474 }
475 else
476 line = end + 1;
477 *end = '\0';
478 return(field);
479 }
480
481 struct AuthBlock *find_matching_conf(struct AuthBlock *acptr)
482 {
483 struct AuthBlock *ptr;
484
485 for(ptr = auth_spoof; ptr; ptr = ptr->next)
486 {
487 if(match(ptr, acptr))
488 return ptr;
489 }
490
491 for(ptr = auth_special; ptr; ptr = ptr->next)
492 {
493 if(match(ptr, acptr))
494 return ptr;
495 }
496
497 for(ptr = auth_passwd; ptr; ptr = ptr->next)
498 {
499 if(match(ptr, acptr))
500 return ptr;
501 }
502
503 for(ptr = auth_restricted; ptr; ptr = ptr->next)
504 {
505 if(match(ptr, acptr))
506 return ptr;
507 }
508
509 for(ptr = auth_general; ptr; ptr = ptr->next)
510 {
511 if(match(ptr, acptr))
512 return ptr;
513 }
514
515
516 return NULL;
517 }
518
519 static int match(struct AuthBlock *ptr, struct AuthBlock *acptr)
520 {
521 if((ptr->class == acptr->class) &&
522 (ptr->flags == acptr->flags))
523 {
524 const char *p1, *p2;
525
526 /* check the spoofs match.. */
527 if(ptr->spoof)
528 p1 = ptr->spoof;
529 else
530 p1 = "";
531
532 if(acptr->spoof)
533 p2 = acptr->spoof;
534 else
535 p2 = "";
536
537 if(strcmp(p1, p2))
538 return 0;
539
540 /* now check the passwords match.. */
541 if(ptr->passwd)
542 p1 = ptr->passwd;
543 else
544 p1 = "";
545
546 if(acptr->passwd)
547 p2 = acptr->passwd;
548 else
549 p2 = "";
550
551 if(strcmp(p1, p2))
552 return 0;
553
554 return 1;
555 }
556
557 return 0;
558 }
559
560 void set_flags(struct AuthBlock *ptr, const char *user_field, const char *host_field)
561 {
562 for(; *user_field; user_field++)
563 {
564 switch(*user_field)
565 {
566 case '=':
567 if(host_field)
568 ptr->spoof = strdup(host_field);
569
570 ptr->special = 1;
571 break;
572
573 case '-':
574 ptr->flags |= FLAGS_NOTILDE;
575 ptr->special = 1;
576 break;
577
578 case '+':
579 ptr->flags |= FLAGS_NEEDIDENT;
580 ptr->specialk = 1;
581 break;
582
583 case '^': /* is exempt from k/g lines */
584 ptr->flags |= FLAGS_KLINEEXEMPT;
585 ptr->special = 1;
586 break;
587
588 case '>':
589 ptr->flags |= FLAGS_EXCEEDLIMIT;
590 ptr->special = 1;
591 break;
592
593 case '!':
594 case '$':
595 case '%':
596 case '&':
597 case '<':
598 break;
599
600 default:
601 {
602 int authindex;
603 authindex = ptr->hostnum;
604 ptr->hostnum++;
605
606 ptr->hostname = realloc((void *)ptr->hostname, ptr->hostnum * sizeof(void *));
607
608 /* if the IP field contains something useful, use that */
609 if(strcmp(host_field, "NOMATCH") && (*host_field != 'x') &&
610 strcmp(host_field, "*") && !ptr->spoof)
611 ptr->hostname[authindex] = strdup(host_field);
612 else
613 ptr->hostname[authindex] = strdup(user_field);
614
615 return;
616 }
617 }
618 }
619 }
620