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