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