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