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