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