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