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