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