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