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       /* Check whether this connection is backup router connection */
955       ret = silc_config_get_token(line, &tmp);
956       if (ret != -1) {
957         config->routers->backup_router = atoi(tmp);
958         if (config->routers->backup_router != 0)
959           config->routers->backup_router = TRUE;
960         silc_free(tmp);
961       }
962
963       /* Check whether this backup is local (in cell) or remote (other cell) */
964       ret = silc_config_get_token(line, &tmp);
965       if (ret != -1) {
966         config->routers->backup_local = atoi(tmp);
967         if (config->routers->backup_local != 0)
968           config->routers->backup_local = TRUE;
969         silc_free(tmp);
970       }
971
972       check = TRUE;
973       checkmask |= (1L << pc->section->type);
974       break;
975
976     case SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_CONNECTION:
977
978       SILC_SERVER_CONFIG_LIST_ALLOC(config->admins);
979
980       /* Get host */
981       ret = silc_config_get_token(line, &config->admins->host);
982       if (ret < 0)
983         break;
984       if (ret == 0)
985         /* Any host */
986         config->admins->host = strdup("*");
987
988       /* Get username */
989       ret = silc_config_get_token(line, &config->admins->username);
990       if (ret < 0)
991         break;
992       if (ret == 0)
993         /* Any username */
994         config->admins->username = strdup("*");
995
996       /* Get nickname */
997       ret = silc_config_get_token(line, &config->admins->nickname);
998       if (ret < 0)
999         break;
1000       if (ret == 0)
1001         /* Any nickname */
1002         config->admins->nickname = strdup("*");
1003
1004       /* Get authentication method */
1005       ret = silc_config_get_token(line, &tmp);
1006       if (ret < 0)
1007         break;
1008       if (ret) {
1009         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
1010             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
1011           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
1012                   config->filename, pc->linenum, tmp);
1013           break;
1014         }
1015
1016         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
1017           config->admins->auth_meth = SILC_AUTH_PASSWORD;
1018
1019         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
1020           config->admins->auth_meth = SILC_AUTH_PUBLIC_KEY;
1021
1022         silc_free(tmp);
1023       }
1024
1025       /* Get authentication data */
1026       ret = silc_config_get_token(line, (char **)&config->admins->auth_data);
1027       if (ret < 0)
1028         break;
1029
1030       if (config->admins->auth_meth == SILC_AUTH_PASSWORD) {
1031         config->admins->auth_data_len = strlen(config->admins->auth_data);
1032       } else if (config->admins->auth_meth == SILC_AUTH_PUBLIC_KEY) {
1033         /* Get the public key */
1034         SilcPublicKey public_key;
1035
1036         if (!silc_pkcs_load_public_key(config->admins->auth_data,
1037                                        &public_key, SILC_PKCS_FILE_PEM))
1038           if (!silc_pkcs_load_public_key(config->admins->auth_data,
1039                                          &public_key, SILC_PKCS_FILE_BIN)) {
1040             fprintf(stderr, "%s:%d: Could not load public key file `%s'\n",
1041                     config->filename, pc->linenum, 
1042                     (char *)config->admins->auth_data);
1043             break;
1044           }
1045
1046         silc_free(config->admins->auth_data);
1047         config->admins->auth_data = (void *)public_key;
1048         config->admins->auth_data_len = 0;
1049       }
1050
1051       check = TRUE;
1052       checkmask |= (1L << pc->section->type);
1053       break;
1054
1055     case SILC_CONFIG_SERVER_SECTION_TYPE_DENY_CONNECTION:
1056
1057       SILC_SERVER_CONFIG_LIST_ALLOC(config->denied);
1058
1059       /* Get host */
1060       ret = silc_config_get_token(line, &config->denied->host);
1061       if (ret < 0)
1062         break;
1063       if (ret == 0) {
1064         /* Any host */
1065         config->denied->host = strdup("*");
1066         fprintf(stderr, "warning: %s:%d: Denying all connections",
1067                 config->filename, pc->linenum);
1068       }
1069
1070       /* Get port */
1071       ret = silc_config_get_token(line, &tmp);
1072       if (ret < 0)
1073         break;
1074       if (ret == 0) {
1075         /* Any port */
1076         config->denied->port = 0;
1077       } else {
1078         config->denied->port = atoi(tmp);
1079         silc_free(tmp);
1080       }
1081
1082       /* Get comment */
1083       ret = silc_config_get_token(line, &config->denied->comment);
1084       if (ret < 0)
1085         break;
1086
1087       check = TRUE;
1088       checkmask |= (1L << pc->section->type);
1089       break;
1090
1091     case SILC_CONFIG_SERVER_SECTION_TYPE_MOTD:
1092
1093       if (!config->motd)
1094         config->motd = silc_calloc(1, sizeof(*config->motd));
1095
1096       /* Get motd file */
1097       ret = silc_config_get_token(line, &config->motd->motd_file);
1098       if (ret < 0)
1099         break;
1100
1101       check = TRUE;
1102       checkmask |= (1L << pc->section->type);
1103       break;
1104
1105     case SILC_CONFIG_SERVER_SECTION_TYPE_NONE:
1106     default:
1107       /* Error */
1108       break;
1109     }
1110
1111     /* Check for error */
1112     if (check == FALSE) {
1113       /* Line could not be parsed */
1114       fprintf(stderr, "%s:%d: Parse error\n", config->filename, pc->linenum);
1115       break;
1116     }
1117
1118     pc = pc->next;
1119   }
1120
1121   if (check == FALSE)
1122     return FALSE;;
1123
1124   /* Check that all mandatory sections really were found. If not, the server
1125      cannot function and we return error. */
1126   ret = silc_server_config_check_sections(checkmask);
1127   if (ret == FALSE) {
1128     /* XXX */
1129
1130   }
1131   
1132   /* Before returning all the lists in the config object must be set
1133      to their first values (the last value is first here). */
1134   while (config->cipher && config->cipher->prev)
1135     config->cipher = config->cipher->prev;
1136   while (config->pkcs && config->pkcs->prev)
1137     config->pkcs = config->pkcs->prev;
1138   while (config->hash_func && config->hash_func->prev)
1139     config->hash_func = config->hash_func->prev;
1140   while (config->hmac && config->hmac->prev)
1141     config->hmac = config->hmac->prev;
1142   while (config->listen_port && config->listen_port->prev)
1143     config->listen_port = config->listen_port->prev;
1144   while (config->logging && config->logging->prev)
1145     config->logging = config->logging->prev;
1146   while (config->conn_class && config->conn_class->prev)
1147     config->conn_class = config->conn_class->prev;
1148   while (config->clients && config->clients->prev)
1149     config->clients = config->clients->prev;
1150   while (config->servers && config->servers->prev)
1151     config->servers = config->servers->prev;
1152   while (config->admins && config->admins->prev)
1153     config->admins = config->admins->prev;
1154   while (config->routers && config->routers->prev)
1155     config->routers = config->routers->prev;
1156   
1157   SILC_LOG_DEBUG(("Done"));
1158   
1159   return TRUE;
1160 }
1161
1162 /* This function checks that the mask sent as argument includes all the 
1163    sections that are mandatory in SILC server. */
1164
1165 int silc_server_config_check_sections(uint32 checkmask)
1166 {
1167   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO))) {
1168     
1169     return FALSE;
1170   }
1171   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO))) {
1172     
1173     return FALSE;
1174   }
1175   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT))) {
1176     
1177     return FALSE;
1178   }
1179   if (!(checkmask & 
1180         (1L << SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION))) {
1181     
1182     return FALSE;
1183   }
1184   if (!(checkmask 
1185         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION))) {
1186     
1187     return FALSE;
1188   }
1189   if (!(checkmask 
1190         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION))) {
1191     
1192     return FALSE;
1193   }
1194
1195   return TRUE;
1196 }
1197
1198 /* Sets log files where log messages is saved by the server. */
1199
1200 void silc_server_config_setlogfiles(SilcServerConfig config)
1201 {
1202   SilcServerConfigSectionLogging *log;
1203   char *info, *warning, *error, *fatal;
1204   uint32 info_size, warning_size, error_size, fatal_size;
1205
1206   SILC_LOG_DEBUG(("Setting configured log file names"));
1207
1208   /* Set default files before checking configuration */
1209   info = SILC_LOG_FILE_INFO;
1210   warning = SILC_LOG_FILE_WARNING;
1211   error = SILC_LOG_FILE_ERROR;
1212   fatal = SILC_LOG_FILE_FATAL;
1213   info_size = 0;
1214   warning_size = 0;
1215   error_size = 0;
1216   fatal_size = 0;
1217
1218   log = config->logging;
1219   while(log) {
1220     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_INFO)) {
1221       info = log->filename;
1222       info_size = log->maxsize;
1223     }
1224     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_WARNING)) {
1225       warning = log->filename;
1226       warning_size = log->maxsize;
1227     }
1228     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_ERROR)) {
1229       error = log->filename;
1230       error_size = log->maxsize;
1231     }
1232     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
1233       fatal = log->filename;
1234       fatal_size = log->maxsize;
1235     }
1236
1237     log = log->next;
1238   }
1239
1240   silc_log_set_files(info, info_size, warning, warning_size,
1241                      error, error_size, fatal, fatal_size);
1242 }
1243
1244 /* Registers configured ciphers. These can then be allocated by the
1245    server when needed. */
1246
1247 bool silc_server_config_register_ciphers(SilcServerConfig config)
1248 {
1249   SilcServerConfigSectionAlg *alg;
1250   SilcServer server = (SilcServer)config->server;
1251
1252   SILC_LOG_DEBUG(("Registering configured ciphers"));
1253
1254   if (!config->cipher)
1255     return FALSE;
1256
1257   alg = config->cipher;
1258   while(alg) {
1259
1260     if (!alg->sim_name) {
1261       int i;
1262       
1263       for (i = 0; silc_default_ciphers[i].name; i++)
1264         if (!strcmp(silc_default_ciphers[i].name, alg->alg_name)) {
1265           silc_cipher_register(&silc_default_ciphers[i]);
1266           break;
1267         }
1268       
1269       if (!silc_cipher_is_supported(alg->alg_name)) {
1270         SILC_LOG_ERROR(("Unknown cipher `%s'", alg->alg_name));
1271         silc_server_stop(server);
1272         exit(1);
1273       }
1274 #ifdef SILC_SIM
1275     } else {
1276       /* Load (try at least) the crypto SIM module */
1277       SilcCipherObject cipher;
1278       SilcSimContext *sim;
1279       char *alg_name;
1280
1281       memset(&cipher, 0, sizeof(cipher));
1282       cipher.name = alg->alg_name;
1283       cipher.block_len = alg->block_len;
1284       cipher.key_len = alg->key_len * 8;
1285
1286       sim = silc_sim_alloc();
1287       sim->type = SILC_SIM_CIPHER;
1288       sim->libname = alg->sim_name;
1289
1290       alg_name = strdup(alg->alg_name);
1291       if (strchr(alg_name, '-'))
1292         *strchr(alg_name, '-') = '\0';
1293
1294       if ((silc_sim_load(sim))) {
1295         cipher.set_key = 
1296           silc_sim_getsym(sim, silc_sim_symname(alg_name, 
1297                                                 SILC_CIPHER_SIM_SET_KEY));
1298         SILC_LOG_DEBUG(("set_key=%p", cipher.set_key));
1299         cipher.set_key_with_string = 
1300           silc_sim_getsym(sim, silc_sim_symname(alg_name, 
1301                                                 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1302         SILC_LOG_DEBUG(("set_key_with_string=%p", cipher.set_key_with_string));
1303         cipher.encrypt = 
1304           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1305                                                 SILC_CIPHER_SIM_ENCRYPT_CBC));
1306         SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher.encrypt));
1307         cipher.decrypt = 
1308           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1309                                                 SILC_CIPHER_SIM_DECRYPT_CBC));
1310         SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher.decrypt));
1311         cipher.context_len = 
1312           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1313                                                 SILC_CIPHER_SIM_CONTEXT_LEN));
1314         SILC_LOG_DEBUG(("context_len=%p", cipher.context_len));
1315
1316         /* Put the SIM to the list of all SIM's in server */
1317         silc_dlist_add(server->sim, sim);
1318
1319         silc_free(alg_name);
1320       } else {
1321         SILC_LOG_ERROR(("Error configuring ciphers"));
1322         silc_server_stop(server);
1323         exit(1);
1324       }
1325
1326       /* Register the cipher */
1327       silc_cipher_register(&cipher);
1328 #endif
1329     }
1330
1331     alg = alg->next;
1332   }
1333
1334   return TRUE;
1335 }
1336
1337 /* Registers configured PKCS's. */
1338
1339 bool silc_server_config_register_pkcs(SilcServerConfig config)
1340 {
1341   SilcServerConfigSectionAlg *alg = config->pkcs;
1342   SilcServer server = (SilcServer)config->server;
1343
1344   SILC_LOG_DEBUG(("Registering configured PKCS"));
1345
1346   if (!config->pkcs)
1347     return FALSE;
1348
1349   while(alg) {
1350     int i;
1351     
1352     for (i = 0; silc_default_pkcs[i].name; i++)
1353       if (!strcmp(silc_default_pkcs[i].name, alg->alg_name)) {
1354         silc_pkcs_register(&silc_default_pkcs[i]);
1355         break;
1356       }
1357       
1358     if (!silc_pkcs_is_supported(alg->alg_name)) {
1359       SILC_LOG_ERROR(("Unknown PKCS `%s'", alg->alg_name));
1360       silc_server_stop(server);
1361       exit(1);
1362     }
1363
1364     alg = alg->next;
1365   }
1366
1367   return TRUE;
1368 }
1369
1370 /* Registers configured hash functions. These can then be allocated by the
1371    server when needed. */
1372
1373 bool silc_server_config_register_hashfuncs(SilcServerConfig config)
1374 {
1375   SilcServerConfigSectionAlg *alg;
1376   SilcServer server = (SilcServer)config->server;
1377
1378   SILC_LOG_DEBUG(("Registering configured hash functions"));
1379
1380   if (!config->hash_func)
1381     return FALSE;
1382
1383   alg = config->hash_func;
1384   while(alg) {
1385
1386     if (!alg->sim_name) {
1387       int i;
1388       
1389       for (i = 0; silc_default_hash[i].name; i++)
1390         if (!strcmp(silc_default_hash[i].name, alg->alg_name)) {
1391           silc_hash_register(&silc_default_hash[i]);
1392           break;
1393         }
1394       
1395       if (!silc_hash_is_supported(alg->alg_name)) {
1396         SILC_LOG_ERROR(("Unknown hash funtion `%s'", alg->alg_name));
1397         silc_server_stop(server);
1398         exit(1);
1399       }
1400
1401 #ifdef SILC_SIM
1402     } else {
1403       /* Load (try at least) the hash SIM module */
1404       SilcHashObject hash;
1405       SilcSimContext *sim;
1406
1407       memset(&hash, 0, sizeof(hash));
1408       hash.name = alg->alg_name;
1409       hash.block_len = alg->block_len;
1410       hash.hash_len = alg->key_len;
1411
1412       sim = silc_sim_alloc();
1413       sim->type = SILC_SIM_HASH;
1414       sim->libname = alg->sim_name;
1415
1416       if ((silc_sim_load(sim))) {
1417         hash.init = 
1418           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name, 
1419                                                 SILC_HASH_SIM_INIT));
1420         SILC_LOG_DEBUG(("init=%p", hash.init));
1421         hash.update = 
1422           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1423                                                 SILC_HASH_SIM_UPDATE));
1424         SILC_LOG_DEBUG(("update=%p", hash.update));
1425         hash.final = 
1426           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1427                                                 SILC_HASH_SIM_FINAL));
1428         SILC_LOG_DEBUG(("final=%p", hash.final));
1429         hash.context_len = 
1430           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1431                                                 SILC_HASH_SIM_CONTEXT_LEN));
1432         SILC_LOG_DEBUG(("context_len=%p", hash.context_len));
1433
1434         /* Put the SIM to the table of all SIM's in server */
1435         silc_dlist_add(server->sim, sim);
1436       } else {
1437         SILC_LOG_ERROR(("Error configuring hash functions"));
1438         silc_server_stop(server);
1439         exit(1);
1440       }
1441
1442       /* Register the hash function */
1443       silc_hash_register(&hash);
1444 #endif
1445     }
1446
1447     alg = alg->next;
1448   }
1449
1450   return TRUE;
1451 }
1452
1453 /* Registers configure HMACs. These can then be allocated by the server
1454    when needed. */
1455
1456 bool silc_server_config_register_hmacs(SilcServerConfig config)
1457 {
1458   SilcServerConfigSectionAlg *alg;
1459   SilcServer server = (SilcServer)config->server;
1460
1461   SILC_LOG_DEBUG(("Registering configured HMACs"));
1462
1463   if (!config->hmac)
1464     return FALSE;
1465
1466   alg = config->hmac;
1467   while(alg) {
1468     SilcHmacObject hmac;
1469     
1470     if (!silc_hash_is_supported(alg->sim_name)) {
1471       SILC_LOG_ERROR(("Unknown hash function `%s'", alg->sim_name));
1472       silc_server_stop(server);
1473       exit(1);
1474     }
1475     
1476     /* Register the HMAC */
1477     memset(&hmac, 0, sizeof(hmac));
1478     hmac.name = alg->alg_name;
1479     hmac.len = alg->key_len;
1480     silc_hmac_register(&hmac);
1481
1482     alg = alg->next;
1483   }
1484
1485   return TRUE;
1486 }
1487
1488 /* Returns client authentication information from server configuration
1489    by host (name or ip). If `port' is non-null then both name or IP and 
1490    the port must match. */
1491
1492 SilcServerConfigSectionClientConnection *
1493 silc_server_config_find_client_conn(SilcServerConfig config, 
1494                                     char *host, int port)
1495 {
1496   int i;
1497   SilcServerConfigSectionClientConnection *client = NULL;
1498   bool match = FALSE;
1499
1500   if (!host)
1501     return NULL;
1502
1503   if (!config->clients)
1504     return NULL;
1505
1506   client = config->clients;
1507
1508   for (i = 0; client; i++) {
1509     if (silc_string_compare(client->host, host))
1510       match = TRUE;
1511
1512     if (port && client->port && client->port != port)
1513       match = FALSE;
1514
1515     if (match)
1516       break;
1517
1518     client = client->next;
1519   }
1520
1521   if (!client)
1522     return NULL;
1523
1524   return client;
1525 }
1526
1527 /* Returns server connection info from server configuartion by host 
1528    (name or ip). If `port' is non-null then both name or IP and the port
1529    must match. */
1530
1531 SilcServerConfigSectionServerConnection *
1532 silc_server_config_find_server_conn(SilcServerConfig config, 
1533                                     char *host, int port)
1534 {
1535   int i;
1536   SilcServerConfigSectionServerConnection *serv = NULL;
1537   bool match = FALSE;
1538
1539   if (!host)
1540     return NULL;
1541
1542   if (!config->servers)
1543     return NULL;
1544
1545   serv = config->servers;
1546   for (i = 0; serv; i++) {
1547     if (silc_string_compare(serv->host, host))
1548       match = TRUE;
1549
1550     if (port && serv->port && serv->port != port)
1551       match = FALSE;
1552
1553     if (match)
1554       break;
1555
1556     serv = serv->next;
1557   }
1558
1559   if (!serv)
1560     return NULL;
1561
1562   return serv;
1563 }
1564
1565 /* Returns router connection info from server configuartion by
1566    host (name or ip). */
1567
1568 SilcServerConfigSectionServerConnection *
1569 silc_server_config_find_router_conn(SilcServerConfig config, 
1570                                     char *host, int port)
1571 {
1572   int i;
1573   SilcServerConfigSectionServerConnection *serv = NULL;
1574   bool match = FALSE;
1575
1576   if (!host)
1577     return NULL;
1578
1579   if (!config->routers)
1580     return NULL;
1581
1582   serv = config->routers;
1583   for (i = 0; serv; i++) {
1584     if (silc_string_compare(serv->host, host))
1585       match = TRUE;
1586
1587     if (port && serv->port && serv->port != port)
1588       match = FALSE;
1589
1590     if (match)
1591       break;
1592
1593     serv = serv->next;
1594   }
1595
1596   if (!serv)
1597     return NULL;
1598
1599   return serv;
1600 }
1601
1602 /* Returns TRUE if configuartion for a router connection that we are 
1603    initiating exists. */
1604
1605 bool silc_server_config_is_primary_route(SilcServerConfig config)
1606 {
1607   int i;
1608   SilcServerConfigSectionServerConnection *serv = NULL;
1609   bool found = FALSE;
1610
1611   serv = config->routers;
1612   for (i = 0; serv; i++) {
1613     if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1614       found = TRUE;
1615       break;
1616     }
1617
1618     serv = serv->next;
1619   }
1620
1621   return found;
1622 }
1623
1624 /* Returns our primary connection configuration or NULL if we do not
1625    have primary router configured. */
1626
1627 SilcServerConfigSectionServerConnection *
1628 silc_server_config_get_primary_router(SilcServerConfig config)
1629 {
1630   int i;
1631   SilcServerConfigSectionServerConnection *serv = NULL;
1632
1633   serv = config->routers;
1634   for (i = 0; serv; i++) {
1635     if (serv->initiator == TRUE && serv->backup_router == FALSE)
1636       return serv;
1637     serv = serv->next;
1638   }
1639
1640   return NULL;
1641 }
1642
1643 /* Returns Admin connection configuration by host, username and/or 
1644    nickname. */
1645
1646 SilcServerConfigSectionAdminConnection *
1647 silc_server_config_find_admin(SilcServerConfig config,
1648                               char *host, char *username, char *nickname)
1649 {
1650   SilcServerConfigSectionAdminConnection *admin = NULL;
1651   int i;
1652
1653   if (!config->admins)
1654     return NULL;
1655
1656   if (!host)
1657     host = "*";
1658   if (!username)
1659     username = "*";
1660   if (!nickname)
1661     nickname = "*";
1662
1663   admin = config->admins;
1664   for (i = 0; admin; i++) {
1665     if (silc_string_compare(admin->host, host) &&
1666         silc_string_compare(admin->username, username) &&
1667         silc_string_compare(admin->nickname, nickname))
1668       break;
1669
1670     admin = admin->next;
1671   }
1672
1673   if (!admin)
1674     return NULL;
1675
1676   return admin;
1677 }
1678
1679 /* Returns the Denied connection configuration by host and port. */
1680
1681 SilcServerConfigSectionDenyConnection *
1682 silc_server_config_denied_conn(SilcServerConfig config, char *host,
1683                                int port)
1684 {
1685   int i;
1686   SilcServerConfigSectionDenyConnection *deny = NULL;
1687   bool match = FALSE;
1688
1689   if (!host)
1690     return NULL;
1691
1692   if (!config->denied)
1693     return NULL;
1694
1695   deny = config->denied;
1696   for (i = 0; deny; i++) {
1697     if (silc_string_compare(deny->host, host))
1698       match = TRUE;
1699
1700     if (port && deny->port && deny->port != port)
1701       match = FALSE;
1702
1703     if (match)
1704       break;
1705
1706     deny = deny->next;
1707   }
1708
1709   if (!deny)
1710     return NULL;
1711
1712   return deny;
1713 }