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   }
1033
1034   if (check == FALSE)
1035     return FALSE;;
1036
1037   /* Check that all mandatory sections really were found. If not, the server
1038      cannot function and we return error. */
1039   ret = silc_server_config_check_sections(checkmask);
1040   if (ret == FALSE) {
1041     /* XXX */
1042
1043   }
1044   
1045   /* Before returning all the lists in the config object must be set
1046      to their first values (the last value is first here). */
1047   while (config->cipher && config->cipher->prev)
1048     config->cipher = config->cipher->prev;
1049   while (config->pkcs && config->pkcs->prev)
1050     config->pkcs = config->pkcs->prev;
1051   while (config->hash_func && config->hash_func->prev)
1052     config->hash_func = config->hash_func->prev;
1053   while (config->hmac && config->hmac->prev)
1054     config->hmac = config->hmac->prev;
1055   while (config->listen_port && config->listen_port->prev)
1056     config->listen_port = config->listen_port->prev;
1057   while (config->logging && config->logging->prev)
1058     config->logging = config->logging->prev;
1059   while (config->conn_class && config->conn_class->prev)
1060     config->conn_class = config->conn_class->prev;
1061   while (config->clients && config->clients->prev)
1062     config->clients = config->clients->prev;
1063   while (config->servers && config->servers->prev)
1064     config->servers = config->servers->prev;
1065   while (config->routers && config->routers->prev)
1066     config->routers = config->routers->prev;
1067   
1068   SILC_LOG_DEBUG(("Done"));
1069   
1070   return TRUE;
1071 }
1072
1073 /* This function checks that the mask sent as argument includes all the 
1074    sections that are mandatory in SILC server. */
1075
1076 int silc_server_config_check_sections(unsigned int checkmask)
1077 {
1078   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO))) {
1079     
1080     return FALSE;
1081   }
1082   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO))) {
1083     
1084     return FALSE;
1085   }
1086   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT))) {
1087     
1088     return FALSE;
1089   }
1090   if (!(checkmask & 
1091         (1L << SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION))) {
1092     
1093     return FALSE;
1094   }
1095   if (!(checkmask 
1096         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION))) {
1097     
1098     return FALSE;
1099   }
1100   if (!(checkmask 
1101         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION))) {
1102     
1103     return FALSE;
1104   }
1105
1106   return TRUE;
1107 }
1108
1109 /* Sets log files where log messages is saved by the server. */
1110
1111 void silc_server_config_setlogfiles(SilcServerConfig config)
1112 {
1113   SilcServerConfigSectionLogging *log;
1114   char *info, *warning, *error, *fatal;
1115   unsigned int info_size, warning_size, error_size, fatal_size;
1116
1117   SILC_LOG_DEBUG(("Setting configured log file names"));
1118
1119   /* Set default files before checking configuration */
1120   info = SILC_LOG_FILE_INFO;
1121   warning = SILC_LOG_FILE_WARNING;
1122   error = SILC_LOG_FILE_ERROR;
1123   fatal = SILC_LOG_FILE_FATAL;
1124   info_size = 0;
1125   warning_size = 0;
1126   error_size = 0;
1127   fatal_size = 0;
1128
1129   log = config->logging;
1130   while(log) {
1131     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_INFO)) {
1132       info = log->filename;
1133       info_size = log->maxsize;
1134     }
1135     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_WARNING)) {
1136       warning = log->filename;
1137       warning_size = log->maxsize;
1138     }
1139     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_ERROR)) {
1140       error = log->filename;
1141       error_size = log->maxsize;
1142     }
1143     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
1144       fatal = log->filename;
1145       fatal_size = log->maxsize;
1146     }
1147
1148     log = log->next;
1149   }
1150
1151   silc_log_set_files(info, info_size, warning, warning_size,
1152                      error, error_size, fatal, fatal_size);
1153 }
1154
1155 /* Registers configured ciphers. These can then be allocated by the
1156    server when needed. */
1157
1158 void silc_server_config_register_ciphers(SilcServerConfig config)
1159 {
1160   SilcServerConfigSectionAlg *alg;
1161   SilcServer server = (SilcServer)config->server;
1162
1163   SILC_LOG_DEBUG(("Registering configured ciphers"));
1164
1165   alg = config->cipher;
1166   while(alg) {
1167
1168     if (!alg->sim_name) {
1169       /* Crypto module is supposed to be built in. Nothing to be done
1170          here except to test that the cipher really is built in. */
1171       SilcCipher tmp = NULL;
1172
1173       if (silc_cipher_alloc(alg->alg_name, &tmp) == FALSE) {
1174         SILC_LOG_ERROR(("Unsupported cipher `%s'", alg->alg_name));
1175         silc_server_stop(server);
1176         exit(1);
1177       }
1178       silc_cipher_free(tmp);
1179
1180 #ifdef SILC_SIM
1181     } else {
1182       /* Load (try at least) the crypto SIM module */
1183       SilcCipherObject cipher;
1184       SilcSimContext *sim;
1185       char *alg_name;
1186
1187       memset(&cipher, 0, sizeof(cipher));
1188       cipher.name = alg->alg_name;
1189       cipher.block_len = alg->block_len;
1190       cipher.key_len = alg->key_len * 8;
1191
1192       sim = silc_sim_alloc();
1193       sim->type = SILC_SIM_CIPHER;
1194       sim->libname = alg->sim_name;
1195
1196       alg_name = strdup(alg->alg_name);
1197       if (strchr(alg_name, '-'))
1198         *strchr(alg_name, '-') = '\0';
1199
1200       if ((silc_sim_load(sim))) {
1201         cipher.set_key = 
1202           silc_sim_getsym(sim, silc_sim_symname(alg_name, 
1203                                                 SILC_CIPHER_SIM_SET_KEY));
1204         SILC_LOG_DEBUG(("set_key=%p", cipher.set_key));
1205         cipher.set_key_with_string = 
1206           silc_sim_getsym(sim, silc_sim_symname(alg_name, 
1207                                                 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1208         SILC_LOG_DEBUG(("set_key_with_string=%p", cipher.set_key_with_string));
1209         cipher.encrypt = 
1210           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1211                                                 SILC_CIPHER_SIM_ENCRYPT_CBC));
1212         SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher.encrypt));
1213         cipher.decrypt = 
1214           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1215                                                 SILC_CIPHER_SIM_DECRYPT_CBC));
1216         SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher.decrypt));
1217         cipher.context_len = 
1218           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1219                                                 SILC_CIPHER_SIM_CONTEXT_LEN));
1220         SILC_LOG_DEBUG(("context_len=%p", cipher.context_len));
1221
1222         /* Put the SIM to the list of all SIM's in server */
1223         silc_dlist_add(server->sim, sim);
1224
1225         silc_free(alg_name);
1226       } else {
1227         SILC_LOG_ERROR(("Error configuring ciphers"));
1228         silc_server_stop(server);
1229         exit(1);
1230       }
1231
1232       /* Register the cipher */
1233       silc_cipher_register(&cipher);
1234 #endif
1235     }
1236
1237     alg = alg->next;
1238   }
1239 }
1240
1241 /* Registers configured PKCS's. */
1242 /* XXX: This really doesn't do anything now since we have statically
1243    registered our PKCS's. This should be implemented when PKCS works
1244    as SIM's. This checks now only that the PKCS user requested is 
1245    really out there. */
1246
1247 void silc_server_config_register_pkcs(SilcServerConfig config)
1248 {
1249   SilcServerConfigSectionAlg *alg = config->pkcs;
1250   SilcServer server = (SilcServer)config->server;
1251   SilcPKCS tmp = NULL;
1252
1253   SILC_LOG_DEBUG(("Registering configured PKCS"));
1254
1255   while(alg) {
1256
1257     if (silc_pkcs_alloc(alg->alg_name, &tmp) == FALSE) {
1258       SILC_LOG_ERROR(("Unsupported PKCS `%s'", alg->alg_name));
1259       silc_server_stop(server);
1260       exit(1);
1261     }
1262     silc_free(tmp);
1263
1264     alg = alg->next;
1265   }
1266 }
1267
1268 /* Registers configured hash functions. These can then be allocated by the
1269    server when needed. */
1270
1271 void silc_server_config_register_hashfuncs(SilcServerConfig config)
1272 {
1273   SilcServerConfigSectionAlg *alg;
1274   SilcServer server = (SilcServer)config->server;
1275
1276   SILC_LOG_DEBUG(("Registering configured hash functions"));
1277
1278   alg = config->hash_func;
1279   while(alg) {
1280
1281     if (!alg->sim_name) {
1282       /* Hash module is supposed to be built in. Nothing to be done
1283          here except to test that the hash function really is built in. */
1284       SilcHash tmp = NULL;
1285
1286       if (silc_hash_alloc(alg->alg_name, &tmp) == FALSE) {
1287         SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->alg_name));
1288         silc_server_stop(server);
1289         exit(1);
1290       }
1291       silc_hash_free(tmp);
1292
1293 #ifdef SILC_SIM
1294     } else {
1295       /* Load (try at least) the hash SIM module */
1296       SilcHashObject hash;
1297       SilcSimContext *sim;
1298
1299       memset(&hash, 0, sizeof(hash));
1300       hash.name = alg->alg_name;
1301       hash.block_len = alg->block_len;
1302       hash.hash_len = alg->key_len;
1303
1304       sim = silc_sim_alloc();
1305       sim->type = SILC_SIM_HASH;
1306       sim->libname = alg->sim_name;
1307
1308       if ((silc_sim_load(sim))) {
1309         hash.init = 
1310           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name, 
1311                                                 SILC_HASH_SIM_INIT));
1312         SILC_LOG_DEBUG(("init=%p", hash.init));
1313         hash.update = 
1314           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1315                                                 SILC_HASH_SIM_UPDATE));
1316         SILC_LOG_DEBUG(("update=%p", hash.update));
1317         hash.final = 
1318           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1319                                                 SILC_HASH_SIM_FINAL));
1320         SILC_LOG_DEBUG(("final=%p", hash.final));
1321         hash.context_len = 
1322           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1323                                                 SILC_HASH_SIM_CONTEXT_LEN));
1324         SILC_LOG_DEBUG(("context_len=%p", hash.context_len));
1325
1326         /* Put the SIM to the table of all SIM's in server */
1327         silc_dlist_add(server->sim, sim);
1328       } else {
1329         SILC_LOG_ERROR(("Error configuring hash functions"));
1330         silc_server_stop(server);
1331         exit(1);
1332       }
1333
1334       /* Register the hash function */
1335       silc_hash_register(&hash);
1336 #endif
1337     }
1338
1339     alg = alg->next;
1340   }
1341 }
1342
1343 /* Registers configure HMACs. These can then be allocated by the server
1344    when needed. */
1345
1346 void silc_server_config_register_hmacs(SilcServerConfig config)
1347 {
1348   SilcServerConfigSectionAlg *alg;
1349   SilcServer server = (SilcServer)config->server;
1350
1351   SILC_LOG_DEBUG(("Registering configured HMACs"));
1352
1353   if (!config->hmac) {
1354     SILC_LOG_ERROR(("HMACs are not configured. SILC cannot work without "
1355                     "HMACs"));
1356     silc_server_stop(server);
1357     exit(1);
1358   }
1359
1360   alg = config->hmac;
1361   while(alg) {
1362     SilcHmacObject hmac;
1363     
1364     if (!silc_hash_is_supported(alg->sim_name)) {
1365       SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->sim_name));
1366       silc_server_stop(server);
1367       exit(1);
1368     }
1369     
1370     /* Register the HMAC */
1371     memset(&hmac, 0, sizeof(hmac));
1372     hmac.name = alg->alg_name;
1373     hmac.len = alg->key_len;
1374     silc_hmac_register(&hmac);
1375
1376     alg = alg->next;
1377   }
1378 }
1379
1380 /* Returns client authentication information from server configuration
1381    by host (name or ip). */
1382
1383 SilcServerConfigSectionClientConnection *
1384 silc_server_config_find_client_conn(SilcServerConfig config, 
1385                                     char *host, int port)
1386 {
1387   int i;
1388   SilcServerConfigSectionClientConnection *client = NULL;
1389
1390   if (!host)
1391     return NULL;
1392
1393   if (!config->clients)
1394     return NULL;
1395
1396   client = config->clients;
1397
1398   for (i = 0; client; i++) {
1399     if (silc_string_compare(client->host, host))
1400       break;
1401     client = client->next;
1402   }
1403
1404   if (!client)
1405     return NULL;
1406
1407   return client;
1408 }
1409
1410 /* Returns server connection info from server configuartion by host 
1411    (name or ip). */
1412
1413 SilcServerConfigSectionServerConnection *
1414 silc_server_config_find_server_conn(SilcServerConfig config, 
1415                                     char *host, int port)
1416 {
1417   int i;
1418   SilcServerConfigSectionServerConnection *serv = NULL;
1419
1420   if (!host)
1421     return NULL;
1422
1423   if (!config->servers)
1424     return NULL;
1425
1426   serv = config->servers;
1427   for (i = 0; serv; i++) {
1428     if (silc_string_compare(serv->host, host))
1429       break;
1430     serv = serv->next;
1431   }
1432
1433   if (!serv)
1434     return NULL;
1435
1436   return serv;
1437 }
1438
1439 /* Returns router connection info from server configuartion by
1440    host (name or ip). */
1441
1442 SilcServerConfigSectionServerConnection *
1443 silc_server_config_find_router_conn(SilcServerConfig config, 
1444                                     char *host, int port)
1445 {
1446   int i;
1447   SilcServerConfigSectionServerConnection *serv = NULL;
1448
1449   if (!host)
1450     return NULL;
1451
1452   if (!config->routers)
1453     return NULL;
1454
1455   serv = config->routers;
1456   for (i = 0; serv; i++) {
1457     if (silc_string_compare(serv->host, host))
1458       break;
1459     serv = serv->next;
1460   }
1461
1462   if (!serv)
1463     return NULL;
1464
1465   return serv;
1466 }
1467
1468 /* Returns Admin connection configuration by host, username and/or 
1469    nickname. */
1470
1471 SilcServerConfigSectionAdminConnection *
1472 silc_server_config_find_admin(SilcServerConfig config,
1473                               char *host, char *username, char *nickname)
1474 {
1475   SilcServerConfigSectionAdminConnection *admin = NULL;
1476   int i;
1477
1478   if (!config->admins)
1479     return NULL;
1480
1481   if (!host)
1482     host = "*";
1483   if (!username)
1484     username = "*";
1485   if (!nickname)
1486     nickname = "*";
1487
1488   admin = config->admins;
1489   for (i = 0; admin; i++) {
1490     if (silc_string_compare(admin->host, host) &&
1491         silc_string_compare(admin->username, username) &&
1492         silc_string_compare(admin->nickname, nickname))
1493       break;
1494
1495     admin = admin->next;
1496   }
1497
1498   if (!admin)
1499     return NULL;
1500
1501   return admin;
1502 }
1503
1504 /* Prints out example configuration file with default built in
1505    configuration values. */
1506
1507 void silc_server_config_print()
1508 {
1509   char *buf;
1510
1511   buf = "\
1512 #\n\
1513 # Automatically generated example SILCd configuration file with default\n\
1514 # built in values. Use this as a guide to configure your SILCd configuration\n\
1515 # file for your system. For detailed description of different configuration\n\
1516 # sections refer to silcd(8) manual page.\n\
1517 #\n";
1518   /*
1519 #<Cipher>
1520 #+blowfish
1521 #+twofish
1522 #+rc5
1523 #+rc6
1524 #+3des
1525
1526 #<HashFunction>
1527 #+md5
1528 #+sha1
1529
1530 <ServerInfo>
1531 +lassi.kuo.fi.ssh.com:10.2.1.6:Kuopio, Finland:1333
1532
1533 <AdminInfo>
1534 +Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
1535
1536 <ListenPort>
1537 +10.2.1.6:10.2.1.6:1333
1538
1539 <Logging>
1540 +infologfile:silcd.log:10000
1541 #+warninglogfile:/var/log/silcd_warning.log:10000
1542 #+errorlogfile:ERROR.log:10000
1543 #+fatallogfile:/var/log/silcd_error.log:
1544
1545 <ConnectionClass>
1546                 +1:100:100:100
1547                         +2:200:300:400
1548
1549 <ClientAuth>
1550 +10.2.1.199:priikone:333:1
1551
1552 <AdminAuth>
1553 +10.2.1.199:priikone:priikone:1
1554
1555 <ServerConnection>
1556
1557 <RouterConnection>
1558
1559 <DenyConnection>
1560 <RedirectClient>
1561   */
1562
1563   fprintf(stdout, "%s\n", buf);
1564 }