updates.
[silc.git] / apps / silcd / serverconfig.c
1 /*
2
3   serverconfig.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 SilcServerConfigSection silc_server_config_sections[] = {
26   { "[Cipher]", 
27     SILC_CONFIG_SERVER_SECTION_TYPE_CIPHER, 4 },
28   { "[PKCS]", 
29     SILC_CONFIG_SERVER_SECTION_TYPE_PKCS, 2 },
30   { "[Hash]", 
31     SILC_CONFIG_SERVER_SECTION_TYPE_HASH_FUNCTION, 4 },
32   { "[hmac]", 
33     SILC_CONFIG_SERVER_SECTION_TYPE_HMAC, 3 },
34   { "[ServerInfo]", 
35     SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO, 4 },
36   { "[AdminInfo]", 
37     SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO, 4 },
38   { "[ListenPort]", 
39     SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT, 3 },
40   { "[Identity]", 
41     SILC_CONFIG_SERVER_SECTION_TYPE_IDENTITY, 2 },
42   { "[Logging]", 
43     SILC_CONFIG_SERVER_SECTION_TYPE_LOGGING, 3 },
44   { "[ConnectionClass]", 
45     SILC_CONFIG_SERVER_SECTION_TYPE_CONNECTION_CLASS, 4 },
46   { "[ClientConnection]", 
47     SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION, 5 },
48   { "[ServerConnection]", 
49     SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION, 6 },
50   { "[RouterConnection]", 
51     SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION, 7 },
52   { "[AdminConnection]", 
53     SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_CONNECTION, 5 },
54   { "[DenyConnection]", 
55     SILC_CONFIG_SERVER_SECTION_TYPE_DENY_CONNECTION, 4 },
56   { "[RedirectClient]", 
57     SILC_CONFIG_SERVER_SECTION_TYPE_REDIRECT_CLIENT, 2 },
58   { "[motd]", 
59     SILC_CONFIG_SERVER_SECTION_TYPE_MOTD, 1 },
60   
61   { NULL, SILC_CONFIG_SERVER_SECTION_TYPE_NONE, 0 }
62 };
63
64 /* Allocates a new configuration object, opens configuration file and
65    parses the file. The parsed data is returned to the newly allocated
66    configuration object. */
67
68 SilcServerConfig silc_server_config_alloc(char *filename)
69 {
70   SilcServerConfig new;
71   SilcBuffer buffer;
72   SilcServerConfigParse config_parse;
73
74   SILC_LOG_DEBUG(("Allocating new configuration object"));
75
76   new = silc_calloc(1, sizeof(*new));
77   if (!new) {
78     fprintf(stderr, "Could not allocate new configuration object");
79     return NULL;
80   }
81
82   new->filename = filename;
83
84   /* Open configuration file and parse it */
85   config_parse = NULL;
86   buffer = NULL;
87   silc_config_open(filename, &buffer);
88   if (!buffer)
89     goto fail;
90   if ((silc_server_config_parse(new, buffer, &config_parse)) == FALSE)
91     goto fail;
92   if ((silc_server_config_parse_lines(new, config_parse)) == FALSE)
93     goto fail;
94
95   silc_free(buffer);
96
97   return new;
98
99  fail:
100   silc_free(new);
101   return NULL;
102 }
103
104 /* Free's a configuration object. */
105
106 void silc_server_config_free(SilcServerConfig config)
107 {
108   if (config) {
109     silc_free(config->filename);
110     silc_free(config->server_info);
111     silc_free(config->admin_info);
112     silc_free(config->listen_port);
113     silc_free(config->identity);
114     silc_free(config->conn_class);
115     silc_free(config->clients);
116     silc_free(config->admins);
117     silc_free(config->servers);
118     silc_free(config->routers);
119     silc_free(config->denied);
120     silc_free(config->redirect);
121     silc_free(config->motd);
122     silc_free(config);
123   }
124 }
125
126 /* Parses the the buffer and returns the parsed lines into return_config
127    argument. The return_config argument doesn't have to be initialized 
128    before calling this. It will be initialized during the parsing. The
129    buffer sent as argument can be safely free'd after this function has
130    succesfully returned. */
131
132 int silc_server_config_parse(SilcServerConfig config, SilcBuffer buffer, 
133                              SilcServerConfigParse *return_config)
134 {
135   int i, begin;
136   unsigned int linenum;
137   char line[1024], *cp;
138   SilcServerConfigSection *cptr = NULL;
139   SilcServerConfigParse parse = *return_config, first = NULL;
140
141   SILC_LOG_DEBUG(("Parsing configuration file"));
142
143   begin = 0;
144   linenum = 0;
145   while((begin = silc_gets(line, sizeof(line), 
146                            buffer->data, buffer->len, begin)) != EOF) {
147     cp = line;
148     linenum++;
149
150     /* Check for bad line */
151     if (silc_check_line(cp))
152       continue;
153
154     /* Remove tabs and whitespaces from the line */
155     if (strchr(cp, '\t')) {
156       i = 0;
157       while(strchr(cp + i, '\t')) {
158         *strchr(cp + i, '\t') = ' ';
159         i++;
160       }
161     }
162     for (i = 0; i < strlen(cp); i++) {
163       if (cp[i] != ' ') {
164         if (i)
165           cp++;
166         break;
167       }
168       cp++;
169     }
170
171     /* Parse line */
172     switch(cp[0]) {
173     case '[':
174       /*
175        * Start of a section
176        */
177
178       /* Remove new line sign */
179       if (strchr(cp, '\n'))
180         *strchr(cp, '\n') = '\0';
181       
182       /* Check for matching sections */
183       for (cptr = silc_server_config_sections; cptr->section; cptr++)
184         if (!strncasecmp(cp, cptr->section, strlen(cptr->section)))
185           break;
186
187       if (!cptr->section) {
188         fprintf(stderr, "%s:%d: Unknown section `%s'\n", 
189                         config->filename, linenum, cp);
190         return FALSE;
191       }
192
193       break;
194     default:
195       /*
196        * Start of a configuration line
197        */
198
199       if (cptr->type != SILC_CONFIG_SERVER_SECTION_TYPE_NONE) {
200         
201         if (strchr(cp, '\n'))
202             *strchr(cp, '\n') = ':';
203
204         if (parse == NULL) {
205           parse = silc_calloc(1, sizeof(*parse));
206           parse->line = NULL;
207           parse->section = NULL;
208           parse->next = NULL;
209           parse->prev = NULL;
210         } else {
211           if (parse->next == NULL) {
212             parse->next = silc_calloc(1, sizeof(*parse->next));
213             parse->next->line = NULL;
214             parse->next->section = NULL;
215             parse->next->next = NULL;
216             parse->next->prev = parse;
217             parse = parse->next;
218           }
219         }
220         
221         if (first == NULL)
222           first = parse;
223
224         /* Add the line to parsing structure for further parsing. */
225         if (parse) {
226           parse->section = cptr;
227           parse->line = silc_buffer_alloc(strlen(cp) + 1);
228           parse->linenum = linenum;
229           silc_buffer_pull_tail(parse->line, strlen(cp));
230           silc_buffer_put(parse->line, cp, strlen(cp));
231         }
232       }
233       break;
234     }
235   }
236   
237   /* Set the return_config argument to its first value so that further
238      parsing can be started from the first line. */
239   *return_config = first;
240
241   return TRUE;
242 }
243
244 /* Parses the lines earlier read from configuration file. The config object
245    must not be initialized, it will be initialized in this function. The
246    parse_config argument is uninitialized automatically during this
247    function. */
248
249 int silc_server_config_parse_lines(SilcServerConfig config, 
250                                    SilcServerConfigParse parse_config)
251 {
252   int ret, check = FALSE;
253   unsigned int checkmask;
254   char *tmp;
255   SilcServerConfigParse pc = parse_config;
256   SilcBuffer line;
257
258   SILC_LOG_DEBUG(("Parsing configuration lines"));
259   
260   if (!config)
261     return FALSE;
262   
263   checkmask = 0;
264   while(pc) {
265     check = FALSE;
266     line = pc->line;
267
268     /* Get number of tokens in line */
269     ret = silc_config_check_num_token(line);
270     if (ret != pc->section->maxfields) {
271       /* Bad line */
272       fprintf(stderr, "%s:%d: Missing tokens, %d tokens (should be %d)\n",
273               config->filename, pc->linenum, ret, 
274               pc->section->maxfields);
275       break;
276     }
277
278     /* Parse the line */
279     switch(pc->section->type) {
280     case SILC_CONFIG_SERVER_SECTION_TYPE_CIPHER:
281
282       SILC_SERVER_CONFIG_LIST_ALLOC(config->cipher);
283
284       /* Get cipher name */
285       ret = silc_config_get_token(line, &config->cipher->alg_name);
286       if (ret < 0)
287         break;
288       if (ret == 0) {
289         fprintf(stderr, "%s:%d: Cipher name not defined\n",
290                 config->filename, pc->linenum);
291         break;
292       }
293
294       /* Get module name */
295       config->cipher->sim_name = NULL;
296       ret = silc_config_get_token(line, &config->cipher->sim_name);
297       if (ret < 0)
298         break;
299
300       /* Get key length */
301       ret = silc_config_get_token(line, &tmp);
302       if (ret < 0)
303         break;
304       if (ret == 0) {
305         fprintf(stderr, "%s:%d: Cipher key length not defined\n",
306                 config->filename, pc->linenum);
307         break;
308       }
309       config->cipher->key_len = atoi(tmp);
310       silc_free(tmp);
311
312       /* Get block length */
313       ret = silc_config_get_token(line, &tmp);
314       if (ret < 0)
315         break;
316       if (ret == 0) {
317         fprintf(stderr, "%s:%d: Cipher block length not defined\n",
318                 config->filename, pc->linenum);
319         break;
320       }
321       config->cipher->block_len = atoi(tmp);
322       silc_free(tmp);
323
324       check = TRUE;
325       checkmask |= (1L << pc->section->type);
326       break;
327
328     case SILC_CONFIG_SERVER_SECTION_TYPE_PKCS:
329
330       SILC_SERVER_CONFIG_LIST_ALLOC(config->pkcs);
331
332       /* Get PKCS name */
333       ret = silc_config_get_token(line, &config->pkcs->alg_name);
334       if (ret < 0)
335         break;
336       if (ret == 0) {
337         fprintf(stderr, "%s:%d: PKCS name not defined\n",
338                 config->filename, pc->linenum);
339         break;
340       }
341
342       /* Get key length */
343       ret = silc_config_get_token(line, &tmp);
344       if (ret < 0)
345         break;
346       if (ret == 0) {
347         fprintf(stderr, "%s:%d: PKCS key length not defined\n",
348                 config->filename, pc->linenum);
349         break;
350       }
351       config->pkcs->key_len = atoi(tmp);
352       silc_free(tmp);
353
354       check = TRUE;
355       checkmask |= (1L << pc->section->type);
356       break;
357
358     case SILC_CONFIG_SERVER_SECTION_TYPE_HASH_FUNCTION:
359
360       SILC_SERVER_CONFIG_LIST_ALLOC(config->hash_func);
361
362       /* Get Hash function name */
363       ret = silc_config_get_token(line, &config->hash_func->alg_name);
364       if (ret < 0)
365         break;
366       if (ret == 0) {
367         fprintf(stderr, "%s:%d: Hash function name not defined\n",
368                 config->filename, pc->linenum);
369         break;
370       }
371       
372       /* Get Hash function module name */
373       config->hash_func->sim_name = NULL;
374       ret = silc_config_get_token(line, &config->hash_func->sim_name);
375       if (ret < 0)
376         break;
377
378       /* Get block length */
379       ret = silc_config_get_token(line, &tmp);
380       if (ret < 0)
381         break;
382       if (ret == 0) {
383         fprintf(stderr, "%s:%d: Hash function block length not defined\n",
384                 config->filename, pc->linenum);
385         break;
386       }
387       config->hash_func->block_len = atoi(tmp);
388       silc_free(tmp);
389
390       /* Get hash length */
391       ret = silc_config_get_token(line, &tmp);
392       if (ret < 0)
393         break;
394       if (ret == 0) {
395         fprintf(stderr, "%s:%d: Hash function hash length not defined\n",
396                 config->filename, pc->linenum);
397         break;
398       }
399       config->hash_func->key_len = atoi(tmp);
400       silc_free(tmp);
401
402       check = TRUE;
403       checkmask |= (1L << pc->section->type);
404       break;
405
406     case SILC_CONFIG_SERVER_SECTION_TYPE_HMAC:
407
408       SILC_SERVER_CONFIG_LIST_ALLOC(config->hmac);
409
410       /* Get HMAC name */
411       ret = silc_config_get_token(line, &config->hmac->alg_name);
412       if (ret < 0)
413         break;
414       if (ret == 0) {
415         fprintf(stderr, "%s:%d: HMAC name not defined\n",
416                 config->filename, pc->linenum);
417         break;
418       }
419
420       /* Get hash name */
421       ret = silc_config_get_token(line, &config->hmac->sim_name);
422       if (ret < 0)
423         break;
424       if (ret == 0) {
425         fprintf(stderr, "%s:%d: Hash function name not defined\n",
426                 config->filename, pc->linenum);
427         break;
428       }
429       
430       /* Get MAC length */
431       ret = silc_config_get_token(line, &tmp);
432       if (ret < 0)
433         break;
434       if (ret == 0) {
435         fprintf(stderr, "%s:%d: HMAC's MAC length not defined\n",
436                 config->filename, pc->linenum);
437         break;
438       }
439       config->hmac->key_len = atoi(tmp);
440       silc_free(tmp);
441
442       check = TRUE;
443       checkmask |= (1L << pc->section->type);
444       break;
445
446     case SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO:
447
448       if (!config->server_info)
449         config->server_info = silc_calloc(1, sizeof(*config->server_info));
450
451       /* Get server name */
452       ret = silc_config_get_token(line, &config->server_info->server_name);
453       if (ret < 0)
454         break;
455       if (ret == 0) {
456         /* Server name not defined */
457
458       }
459       
460       /* Get server IP */
461       ret = silc_config_get_token(line, &config->server_info->server_ip);
462       if (ret < 0)
463         break;
464       if (ret == 0) {
465         /* Server IP not defined */
466
467       }
468
469       /* Get server location */
470       ret = silc_config_get_token(line, &config->server_info->location);
471       if (ret < 0)
472         break;
473
474       /* Get server port */
475       /* XXX: Need port here??? */
476       ret = silc_config_get_token(line, &tmp);
477       if (ret < 0)
478         break;
479       if (ret == 0) {
480         /* Port not defined */
481
482       }
483       config->server_info->port = atoi(tmp);
484       silc_free(tmp);
485
486       check = TRUE;
487       checkmask |= (1L << pc->section->type);
488       break;
489
490     case SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO:
491
492       if (!config->admin_info)
493         config->admin_info = silc_calloc(1, sizeof(*config->admin_info));
494
495       /* Get location */
496       ret = silc_config_get_token(line, &config->admin_info->location);
497       if (ret < 0)
498         break;
499
500       /* Get server type */
501       ret = silc_config_get_token(line, &config->admin_info->server_type);
502       if (ret < 0)
503         break;
504
505       /* Get admins name */
506       ret = silc_config_get_token(line, &config->admin_info->admin_name);
507       if (ret < 0)
508         break;
509
510       /* Get admins email address */
511       ret = silc_config_get_token(line, &config->admin_info->admin_email);
512       if (ret < 0)
513         break;
514
515       check = TRUE;
516       checkmask |= (1L << pc->section->type);
517       break;
518
519     case SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT:
520
521       SILC_SERVER_CONFIG_LIST_ALLOC(config->listen_port);
522
523       /* Get host */
524       ret = silc_config_get_token(line, &config->listen_port->host);
525       if (ret < 0)
526         break;
527
528       /* Get remote IP */
529       ret = silc_config_get_token(line, &config->listen_port->remote_ip);
530       if (ret < 0)
531         break;
532
533       /* Get port */
534       ret = silc_config_get_token(line, &tmp);
535       if (ret < 0)
536         break;
537       if (ret == 0) {
538         /* Any port */
539         config->listen_port->port = 0;
540       } else {
541         config->listen_port->port = atoi(tmp);
542         silc_free(tmp);
543       }
544
545       check = TRUE;
546       checkmask |= (1L << pc->section->type);
547       break;
548
549     case SILC_CONFIG_SERVER_SECTION_TYPE_IDENTITY:
550
551       if (!config->identity)
552         config->identity = silc_calloc(1, sizeof(*config->identity));
553
554       /* Get user */
555       ret = silc_config_get_token(line, &config->identity->user);
556       if (ret < 0)
557         break;
558       /* Get group */
559       ret = silc_config_get_token(line, &config->identity->group);
560       if (ret < 0)
561         break;
562
563       check = TRUE;
564       checkmask |= (1L << pc->section->type);
565
566     case SILC_CONFIG_SERVER_SECTION_TYPE_CONNECTION_CLASS:
567
568       SILC_SERVER_CONFIG_LIST_ALLOC(config->conn_class);
569
570       /* Get class number */
571       ret = silc_config_get_token(line, &tmp);
572       if (ret < 0)
573         break;
574       if (ret == 0) {
575         /* Class number not defined */
576
577       }
578       config->conn_class->class = atoi(tmp);
579       silc_free(tmp);
580
581       /* Get ping frequency */
582       ret = silc_config_get_token(line, &tmp);
583       if (ret < 0)
584         break;
585       config->conn_class->ping_freq = atoi(tmp);
586       silc_free(tmp);
587
588       /* Get connect frequency */
589       ret = silc_config_get_token(line, &tmp);
590       if (ret < 0)
591         break;
592       config->conn_class->connect_freq = atoi(tmp);
593       silc_free(tmp);
594
595       /* Get max links */
596       ret = silc_config_get_token(line, &tmp);
597       if (ret < 0)
598         break;
599       config->conn_class->max_links = atoi(tmp);
600       silc_free(tmp);
601
602       check = TRUE;
603       checkmask |= (1L << pc->section->type);
604       break;
605
606     case SILC_CONFIG_SERVER_SECTION_TYPE_LOGGING:
607
608       SILC_SERVER_CONFIG_LIST_ALLOC(config->logging);
609
610       /* Get log section type and check it */
611       ret = silc_config_get_token(line, &config->logging->logtype);
612       if (ret < 0)
613         break;
614       if (ret == 0) {
615         fprintf(stderr, "%s:%d: Log file section not defined\n", 
616                 config->filename, pc->linenum);
617         break;
618       }
619       if (strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_INFO)
620           && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_WARNING)
621           && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_ERROR)
622           && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
623         fprintf(stderr, "%s:%d: Unknown log file section '%s'\n",
624                 config->filename, pc->linenum, config->logging->logtype);
625         break;
626       }
627
628       /* Get log filename */
629       ret = silc_config_get_token(line, &config->logging->filename);
630       if (ret < 0)
631         break;
632       if (ret == 0) {
633         fprintf(stderr, "%s:%d: Log file name not defined\n",
634                 config->filename, pc->linenum);
635         break;
636       }
637
638       /* Get max byte size */
639       ret = silc_config_get_token(line, &tmp);
640       if (ret < 0)
641         break;
642       if (ret) {
643         config->logging->maxsize = atoi(tmp);
644         silc_free(tmp);
645       }
646
647       check = TRUE;
648       checkmask |= (1L << pc->section->type);
649       break;
650
651     case SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION:
652
653       SILC_SERVER_CONFIG_LIST_ALLOC(config->clients);
654
655       /* Get host */
656       ret = silc_config_get_token(line, &config->clients->host);
657       if (ret < 0)
658         break;
659       if (ret == 0)
660         /* Any host */
661         config->clients->host = strdup("*");
662
663       /* Get authentication method */
664       ret = silc_config_get_token(line, &tmp);
665       if (ret < 0)
666         break;
667       if (ret) {
668         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
669             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
670           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
671                   config->filename, pc->linenum, tmp);
672           break;
673         }
674
675         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
676           config->clients->auth_meth = SILC_AUTH_PASSWORD;
677
678         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
679           config->clients->auth_meth = SILC_AUTH_PUBLIC_KEY;
680
681         silc_free(tmp);
682       }
683
684       /* Get authentication data */
685       ret = silc_config_get_token(line, &config->clients->auth_data);
686       if (ret < 0)
687         break;
688       if (ret == 0)
689         /* Any host */
690         config->clients->host = strdup("*");
691
692       /* Get port */
693       ret = silc_config_get_token(line, &tmp);
694       if (ret < 0)
695         break;
696       if (ret == 0) {
697         config->clients->port = atoi(tmp);
698         silc_free(tmp);
699       }
700
701       /* Get class number */
702       ret = silc_config_get_token(line, &tmp);
703       if (ret < 0)
704         break;
705       if (ret) {
706         config->clients->class = atoi(tmp);
707         silc_free(tmp);
708       }
709
710       check = TRUE;
711       checkmask |= (1L << pc->section->type);
712       break;
713
714     case SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION:
715
716       SILC_SERVER_CONFIG_LIST_ALLOC(config->servers);
717
718       /* Get host */
719       ret = silc_config_get_token(line, &config->servers->host);
720       if (ret < 0)
721         break;
722       if (ret == 0)
723         /* Any host */
724         config->servers->host = strdup("*");
725
726       /* Get authentication method */
727       ret = silc_config_get_token(line, &tmp);
728       if (ret < 0)
729         break;
730       if (ret) {
731         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
732             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
733           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
734                   config->filename, pc->linenum, tmp);
735           break;
736         }
737
738         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
739           config->servers->auth_meth = SILC_AUTH_PASSWORD;
740
741         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
742           config->servers->auth_meth = SILC_AUTH_PUBLIC_KEY;
743
744         silc_free(tmp);
745       }
746
747       /* Get authentication data */
748       ret = silc_config_get_token(line, &config->servers->auth_data);
749       if (ret < 0)
750         break;
751
752       /* Get port */
753       ret = silc_config_get_token(line, &tmp);
754       if (ret < 0)
755         break;
756       if (ret) {
757         config->servers->port = atoi(tmp);
758         silc_free(tmp);
759       }
760
761       /* Get version */
762       ret = silc_config_get_token(line, &config->servers->version);
763       if (ret < 0)
764         break;
765
766       /* Get class number */
767       ret = silc_config_get_token(line, &tmp);
768       if (ret < 0)
769         break;
770       if (ret) {
771         config->servers->class = atoi(tmp);
772         silc_free(tmp);
773       }
774
775       check = TRUE;
776       checkmask |= (1L << pc->section->type);
777       break;
778
779     case SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION:
780
781       SILC_SERVER_CONFIG_LIST_ALLOC(config->routers);
782
783       /* Get host */
784       ret = silc_config_get_token(line, &config->routers->host);
785       if (ret < 0)
786         break;
787       //      if (ret == 0)
788       ///* Any host */
789       //        config->routers->host = strdup("*");
790
791       /* Get authentication method */
792       ret = silc_config_get_token(line, &tmp);
793       if (ret < 0)
794         break;
795       if (ret) {
796         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
797             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
798           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
799                   config->filename, pc->linenum, tmp);
800           break;
801         }
802
803         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
804           config->routers->auth_meth = SILC_AUTH_PASSWORD;
805
806         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
807           config->routers->auth_meth = SILC_AUTH_PUBLIC_KEY;
808
809         silc_free(tmp);
810       }
811
812       /* Get authentication data */
813       ret = silc_config_get_token(line, &config->routers->auth_data);
814       if (ret < 0)
815         break;
816
817       /* Get port */
818       ret = silc_config_get_token(line, &tmp);
819       if (ret < 0)
820         break;
821       if (ret) {
822         config->routers->port = atoi(tmp);
823         silc_free(tmp);
824       }
825
826       /* Get version */
827       ret = silc_config_get_token(line, &config->routers->version);
828       if (ret < 0)
829         break;
830
831       /* Get class number */
832       ret = silc_config_get_token(line, &tmp);
833       if (ret < 0)
834         break;
835       if (ret) {
836         config->routers->class = atoi(tmp);
837         silc_free(tmp);
838       }
839
840       /* Get whether we are initiator or not */
841       ret = silc_config_get_token(line, &tmp);
842       if (ret < 0)
843         break;
844       if (ret) {
845         config->routers->initiator = atoi(tmp);
846         if (config->routers->initiator != 0)
847           config->routers->initiator = TRUE;
848         silc_free(tmp);
849       }
850
851       check = TRUE;
852       checkmask |= (1L << pc->section->type);
853       break;
854
855     case SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_CONNECTION:
856
857       SILC_SERVER_CONFIG_LIST_ALLOC(config->admins);
858
859       /* Get host */
860       ret = silc_config_get_token(line, &config->admins->host);
861       if (ret < 0)
862         break;
863       if (ret == 0)
864         /* Any host */
865         config->admins->host = strdup("*");
866
867       /* Get username */
868       ret = silc_config_get_token(line, &config->admins->username);
869       if (ret < 0)
870         break;
871       if (ret == 0)
872         /* Any username */
873         config->admins->username = strdup("*");
874
875       /* Get nickname */
876       ret = silc_config_get_token(line, &config->admins->nickname);
877       if (ret < 0)
878         break;
879       if (ret == 0)
880         /* Any nickname */
881         config->admins->nickname = strdup("*");
882
883       /* Get authentication method */
884       ret = silc_config_get_token(line, &tmp);
885       if (ret < 0)
886         break;
887       if (ret) {
888         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
889             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
890           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
891                   config->filename, pc->linenum, tmp);
892           break;
893         }
894
895         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
896           config->admins->auth_meth = SILC_AUTH_PASSWORD;
897
898         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
899           config->admins->auth_meth = SILC_AUTH_PUBLIC_KEY;
900
901         silc_free(tmp);
902       }
903
904       /* Get authentication data */
905       ret = silc_config_get_token(line, &config->admins->auth_data);
906       if (ret < 0)
907         break;
908
909       check = TRUE;
910       checkmask |= (1L << pc->section->type);
911       break;
912
913     case SILC_CONFIG_SERVER_SECTION_TYPE_DENY_CONNECTION:
914       /* Not implemented yet */
915       check = TRUE;
916       break;
917
918     case SILC_CONFIG_SERVER_SECTION_TYPE_REDIRECT_CLIENT:
919       /* Not implemented yet */
920       check = TRUE;
921       break;
922
923     case SILC_CONFIG_SERVER_SECTION_TYPE_MOTD:
924
925       if (!config->motd)
926         config->motd = silc_calloc(1, sizeof(*config->motd));
927
928       /* Get motd file */
929       ret = silc_config_get_token(line, &config->motd->motd_file);
930       if (ret < 0)
931         break;
932
933       check = TRUE;
934       checkmask |= (1L << pc->section->type);
935       break;
936
937     case SILC_CONFIG_SERVER_SECTION_TYPE_NONE:
938     default:
939       /* Error */
940       break;
941     }
942
943     /* Check for error */
944     if (check == FALSE) {
945       /* Line could not be parsed */
946       fprintf(stderr, "%s:%d: Parse error\n", config->filename, pc->linenum);
947       break;
948     }
949
950     pc = pc->next;
951     /* XXXX */
952     //    silc_free(pc->prev);
953     //    pc->prev = NULL;
954   }
955
956   if (check == FALSE)
957     return FALSE;;
958
959   /* Check that all mandatory sections really were found. If not, the server
960      cannot function and we return error. */
961   ret = silc_server_config_check_sections(checkmask);
962   if (ret == FALSE) {
963     /* XXX */
964
965   }
966   
967   /* Before returning all the lists in the config object must be set
968      to their first values (the last value is first here). */
969   while (config->cipher && config->cipher->prev)
970     config->cipher = config->cipher->prev;
971   while (config->pkcs && config->pkcs->prev)
972     config->pkcs = config->pkcs->prev;
973   while (config->hash_func && config->hash_func->prev)
974     config->hash_func = config->hash_func->prev;
975   while (config->hmac && config->hmac->prev)
976     config->hmac = config->hmac->prev;
977   while (config->listen_port && config->listen_port->prev)
978     config->listen_port = config->listen_port->prev;
979   while (config->logging && config->logging->prev)
980     config->logging = config->logging->prev;
981   while (config->conn_class && config->conn_class->prev)
982     config->conn_class = config->conn_class->prev;
983   while (config->clients && config->clients->prev)
984     config->clients = config->clients->prev;
985   while (config->servers && config->servers->prev)
986     config->servers = config->servers->prev;
987   while (config->routers && config->routers->prev)
988     config->routers = config->routers->prev;
989   
990   SILC_LOG_DEBUG(("Done"));
991   
992   return TRUE;
993 }
994
995 /* This function checks that the mask sent as argument includes all the 
996    sections that are mandatory in SILC server. */
997
998 int silc_server_config_check_sections(unsigned int checkmask)
999 {
1000   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO))) {
1001     
1002     return FALSE;
1003   }
1004   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO))) {
1005     
1006     return FALSE;
1007   }
1008   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT))) {
1009     
1010     return FALSE;
1011   }
1012   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION))) {
1013     
1014     return FALSE;
1015   }
1016   if (!(checkmask 
1017         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION))) {
1018     
1019     return FALSE;
1020   }
1021   if (!(checkmask 
1022         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION))) {
1023     
1024     return FALSE;
1025   }
1026
1027   return TRUE;
1028 }
1029
1030 /* Sets log files where log messages is saved by the server. */
1031
1032 void silc_server_config_setlogfiles(SilcServerConfig config)
1033 {
1034   SilcServerConfigSectionLogging *log;
1035   char *info, *warning, *error, *fatal;
1036   unsigned int info_size, warning_size, error_size, fatal_size;
1037
1038   SILC_LOG_DEBUG(("Setting configured log file names"));
1039
1040   /* Set default files before checking configuration */
1041   info = SILC_LOG_FILE_INFO;
1042   warning = SILC_LOG_FILE_WARNING;
1043   error = SILC_LOG_FILE_ERROR;
1044   fatal = SILC_LOG_FILE_FATAL;
1045   info_size = 0;
1046   warning_size = 0;
1047   error_size = 0;
1048   fatal_size = 0;
1049
1050   log = config->logging;
1051   while(log) {
1052     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_INFO)) {
1053       info = log->filename;
1054       info_size = log->maxsize;
1055     }
1056     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_WARNING)) {
1057       warning = log->filename;
1058       warning_size = log->maxsize;
1059     }
1060     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_ERROR)) {
1061       error = log->filename;
1062       error_size = log->maxsize;
1063     }
1064     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
1065       fatal = log->filename;
1066       fatal_size = log->maxsize;
1067     }
1068
1069     log = log->next;
1070   }
1071
1072   silc_log_set_files(info, info_size, warning, warning_size,
1073                      error, error_size, fatal, fatal_size);
1074 }
1075
1076 /* Registers configured ciphers. These can then be allocated by the
1077    server when needed. */
1078
1079 void silc_server_config_register_ciphers(SilcServerConfig config)
1080 {
1081   SilcServerConfigSectionAlg *alg;
1082   SilcServer server = (SilcServer)config->server;
1083
1084   SILC_LOG_DEBUG(("Registering configured ciphers"));
1085
1086   alg = config->cipher;
1087   while(alg) {
1088
1089     if (!alg->sim_name) {
1090       /* Crypto module is supposed to be built in. Nothing to be done
1091          here except to test that the cipher really is built in. */
1092       SilcCipher tmp = NULL;
1093
1094       if (silc_cipher_alloc(alg->alg_name, &tmp) == FALSE) {
1095         SILC_LOG_ERROR(("Unsupported cipher `%s'", alg->alg_name));
1096         silc_server_stop(server);
1097         exit(1);
1098       }
1099       silc_cipher_free(tmp);
1100
1101 #ifdef SILC_SIM
1102     } else {
1103       /* Load (try at least) the crypto SIM module */
1104       SilcCipherObject cipher;
1105       SilcSimContext *sim;
1106       char *alg_name;
1107
1108       memset(&cipher, 0, sizeof(cipher));
1109       cipher.name = alg->alg_name;
1110       cipher.block_len = alg->block_len;
1111       cipher.key_len = alg->key_len * 8;
1112
1113       sim = silc_sim_alloc();
1114       sim->type = SILC_SIM_CIPHER;
1115       sim->libname = alg->sim_name;
1116
1117       alg_name = strdup(alg->alg_name);
1118       if (strchr(alg_name, '-'))
1119         *strchr(alg_name, '-') = '\0';
1120
1121       if ((silc_sim_load(sim))) {
1122         cipher.set_key = 
1123           silc_sim_getsym(sim, silc_sim_symname(alg_name, 
1124                                                 SILC_CIPHER_SIM_SET_KEY));
1125         SILC_LOG_DEBUG(("set_key=%p", cipher.set_key));
1126         cipher.set_key_with_string = 
1127           silc_sim_getsym(sim, silc_sim_symname(alg_name, 
1128                                                 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1129         SILC_LOG_DEBUG(("set_key_with_string=%p", cipher.set_key_with_string));
1130         cipher.encrypt = 
1131           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1132                                                 SILC_CIPHER_SIM_ENCRYPT_CBC));
1133         SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher.encrypt));
1134         cipher.decrypt = 
1135           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1136                                                 SILC_CIPHER_SIM_DECRYPT_CBC));
1137         SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher.decrypt));
1138         cipher.context_len = 
1139           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1140                                                 SILC_CIPHER_SIM_CONTEXT_LEN));
1141         SILC_LOG_DEBUG(("context_len=%p", cipher.context_len));
1142
1143         /* Put the SIM to the list of all SIM's in server */
1144         silc_dlist_add(server->sim, sim);
1145
1146         silc_free(alg_name);
1147       } else {
1148         SILC_LOG_ERROR(("Error configuring ciphers"));
1149         silc_server_stop(server);
1150         exit(1);
1151       }
1152
1153       /* Register the cipher */
1154       silc_cipher_register(&cipher);
1155 #endif
1156     }
1157
1158     alg = alg->next;
1159   }
1160 }
1161
1162 /* Registers configured PKCS's. */
1163 /* XXX: This really doesn't do anything now since we have statically
1164    registered our PKCS's. This should be implemented when PKCS works
1165    as SIM's. This checks now only that the PKCS user requested is 
1166    really out there. */
1167
1168 void silc_server_config_register_pkcs(SilcServerConfig config)
1169 {
1170   SilcServerConfigSectionAlg *alg = config->pkcs;
1171   SilcServer server = (SilcServer)config->server;
1172   SilcPKCS tmp = NULL;
1173
1174   SILC_LOG_DEBUG(("Registering configured PKCS"));
1175
1176   while(alg) {
1177
1178     if (silc_pkcs_alloc(alg->alg_name, &tmp) == FALSE) {
1179       SILC_LOG_ERROR(("Unsupported PKCS `%s'", alg->alg_name));
1180       silc_server_stop(server);
1181       exit(1);
1182     }
1183     silc_free(tmp);
1184
1185     alg = alg->next;
1186   }
1187 }
1188
1189 /* Registers configured hash functions. These can then be allocated by the
1190    server when needed. */
1191
1192 void silc_server_config_register_hashfuncs(SilcServerConfig config)
1193 {
1194   SilcServerConfigSectionAlg *alg;
1195   SilcServer server = (SilcServer)config->server;
1196
1197   SILC_LOG_DEBUG(("Registering configured hash functions"));
1198
1199   alg = config->hash_func;
1200   while(alg) {
1201
1202     if (!alg->sim_name) {
1203       /* Hash module is supposed to be built in. Nothing to be done
1204          here except to test that the hash function really is built in. */
1205       SilcHash tmp = NULL;
1206
1207       if (silc_hash_alloc(alg->alg_name, &tmp) == FALSE) {
1208         SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->alg_name));
1209         silc_server_stop(server);
1210         exit(1);
1211       }
1212       silc_hash_free(tmp);
1213
1214 #ifdef SILC_SIM
1215     } else {
1216       /* Load (try at least) the hash SIM module */
1217       SilcHashObject hash;
1218       SilcSimContext *sim;
1219
1220       memset(&hash, 0, sizeof(hash));
1221       hash.name = alg->alg_name;
1222       hash.block_len = alg->block_len;
1223       hash.hash_len = alg->key_len;
1224
1225       sim = silc_sim_alloc();
1226       sim->type = SILC_SIM_HASH;
1227       sim->libname = alg->sim_name;
1228
1229       if ((silc_sim_load(sim))) {
1230         hash.init = 
1231           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name, 
1232                                                 SILC_HASH_SIM_INIT));
1233         SILC_LOG_DEBUG(("init=%p", hash.init));
1234         hash.update = 
1235           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1236                                                 SILC_HASH_SIM_UPDATE));
1237         SILC_LOG_DEBUG(("update=%p", hash.update));
1238         hash.final = 
1239           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1240                                                 SILC_HASH_SIM_FINAL));
1241         SILC_LOG_DEBUG(("final=%p", hash.final));
1242         hash.context_len = 
1243           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1244                                                 SILC_HASH_SIM_CONTEXT_LEN));
1245         SILC_LOG_DEBUG(("context_len=%p", hash.context_len));
1246
1247         /* Put the SIM to the table of all SIM's in server */
1248         silc_dlist_add(server->sim, sim);
1249       } else {
1250         SILC_LOG_ERROR(("Error configuring hash functions"));
1251         silc_server_stop(server);
1252         exit(1);
1253       }
1254
1255       /* Register the hash function */
1256       silc_hash_register(&hash);
1257 #endif
1258     }
1259
1260     alg = alg->next;
1261   }
1262 }
1263
1264 /* Registers configure HMACs. These can then be allocated by the server
1265    when needed. */
1266
1267 void silc_server_config_register_hmacs(SilcServerConfig config)
1268 {
1269   SilcServerConfigSectionAlg *alg;
1270   SilcServer server = (SilcServer)config->server;
1271
1272   SILC_LOG_DEBUG(("Registering configured HMACs"));
1273
1274   if (!config->hmac) {
1275     SILC_LOG_ERROR(("HMACs are not configured. SILC cannot work without "
1276                     "HMACs"));
1277     silc_server_stop(server);
1278     exit(1);
1279   }
1280
1281   alg = config->hmac;
1282   while(alg) {
1283     SilcHmacObject hmac;
1284     
1285     if (!silc_hash_is_supported(alg->sim_name)) {
1286       SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->sim_name));
1287       silc_server_stop(server);
1288       exit(1);
1289     }
1290     
1291     /* Register the HMAC */
1292     memset(&hmac, 0, sizeof(hmac));
1293     hmac.name = alg->alg_name;
1294     hmac.len = alg->key_len;
1295     silc_hmac_register(&hmac);
1296
1297     alg = alg->next;
1298   }
1299 }
1300
1301 /* Returns client authentication information from server configuration
1302    by host (name or ip). */
1303
1304 SilcServerConfigSectionClientConnection *
1305 silc_server_config_find_client_conn(SilcServerConfig config, 
1306                                     char *host, int port)
1307 {
1308   int i;
1309   SilcServerConfigSectionClientConnection *client = NULL;
1310
1311   if (!host)
1312     return NULL;
1313
1314   if (!config->clients)
1315     return NULL;
1316
1317   client = config->clients;
1318
1319   for (i = 0; client; i++) {
1320     if (silc_string_compare(client->host, host))
1321       break;
1322     client = client->next;
1323   }
1324
1325   if (!client)
1326     return NULL;
1327
1328   return client;
1329 }
1330
1331 /* Returns server connection info from server configuartion by host 
1332    (name or ip). */
1333
1334 SilcServerConfigSectionServerConnection *
1335 silc_server_config_find_server_conn(SilcServerConfig config, 
1336                                     char *host, int port)
1337 {
1338   int i;
1339   SilcServerConfigSectionServerConnection *serv = NULL;
1340
1341   if (!host)
1342     return NULL;
1343
1344   if (!config->servers)
1345     return NULL;
1346
1347   serv = config->servers;
1348   for (i = 0; serv; i++) {
1349     if (silc_string_compare(serv->host, host))
1350       break;
1351     serv = serv->next;
1352   }
1353
1354   if (!serv)
1355     return NULL;
1356
1357   return serv;
1358 }
1359
1360 /* Returns router connection info from server configuartion by
1361    host (name or ip). */
1362
1363 SilcServerConfigSectionServerConnection *
1364 silc_server_config_find_router_conn(SilcServerConfig config, 
1365                                     char *host, int port)
1366 {
1367   int i;
1368   SilcServerConfigSectionServerConnection *serv = NULL;
1369
1370   if (!host)
1371     return NULL;
1372
1373   if (!config->routers)
1374     return NULL;
1375
1376   serv = config->routers;
1377   for (i = 0; serv; i++) {
1378     if (silc_string_compare(serv->host, host))
1379       break;
1380     serv = serv->next;
1381   }
1382
1383   if (!serv)
1384     return NULL;
1385
1386   return serv;
1387 }
1388
1389 /* Returns Admin connection configuration by host, username and/or 
1390    nickname. */
1391
1392 SilcServerConfigSectionAdminConnection *
1393 silc_server_config_find_admin(SilcServerConfig config,
1394                               char *host, char *username, char *nickname)
1395 {
1396   SilcServerConfigSectionAdminConnection *admin = NULL;
1397   int i;
1398
1399   if (!config->admins)
1400     return NULL;
1401
1402   if (!host)
1403     host = "*";
1404   if (!username)
1405     username = "*";
1406   if (nickname)
1407     nickname = "*";
1408
1409   admin = config->admins;
1410   for (i = 0; admin; i++) {
1411     if (silc_string_compare(admin->host, host) &&
1412         silc_string_compare(admin->username, username) &&
1413         silc_string_compare(admin->nickname, nickname))
1414       break;
1415
1416     admin = admin->next;
1417   }
1418
1419   if (!admin)
1420     return NULL;
1421
1422   return admin;
1423 }
1424
1425 /* Prints out example configuration file with default built in
1426    configuration values. */
1427
1428 void silc_server_config_print()
1429 {
1430   char *buf;
1431
1432   buf = "\
1433 #\n\
1434 # Automatically generated example SILCd configuration file with default\n\
1435 # built in values. Use this as a guide to configure your SILCd configuration\n\
1436 # file for your system. For detailed description of different configuration\n\
1437 # sections refer to silcd(8) manual page.\n\
1438 #\n";
1439   /*
1440 #<Cipher>
1441 #+blowfish
1442 #+twofish
1443 #+rc5
1444 #+rc6
1445 #+3des
1446
1447 #<HashFunction>
1448 #+md5
1449 #+sha1
1450
1451 <ServerInfo>
1452 +lassi.kuo.fi.ssh.com:10.2.1.6:Kuopio, Finland:1333
1453
1454 <AdminInfo>
1455 +Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
1456
1457 <ListenPort>
1458 +10.2.1.6:10.2.1.6:1333
1459
1460 <Logging>
1461 +infologfile:silcd.log:10000
1462 #+warninglogfile:/var/log/silcd_warning.log:10000
1463 #+errorlogfile:ERROR.log:10000
1464 #+fatallogfile:/var/log/silcd_error.log:
1465
1466 <ConnectionClass>
1467                 +1:100:100:100
1468                         +2:200:300:400
1469
1470 <ClientAuth>
1471 +10.2.1.199:priikone:333:1
1472
1473 <AdminAuth>
1474 +10.2.1.199:priikone:priikone:1
1475
1476 <ServerConnection>
1477
1478 <RouterConnection>
1479
1480 <DenyConnection>
1481 <RedirectClient>
1482   */
1483
1484   fprintf(stdout, "%s\n", buf);
1485 }