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