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