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