032b46d553dbb51562756ea1ed7635e11ba784c0
[silc.git] / apps / silcd / serverconfig.c
1 /*
2
3   serverconfig.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 SilcServerConfigSection silc_server_config_sections[] = {
26   { "[Cipher]", 
27     SILC_CONFIG_SERVER_SECTION_TYPE_CIPHER, 4 },
28   { "[PKCS]", 
29     SILC_CONFIG_SERVER_SECTION_TYPE_PKCS, 2 },
30   { "[Hash]", 
31     SILC_CONFIG_SERVER_SECTION_TYPE_HASH_FUNCTION, 4 },
32   { "[hmac]", 
33     SILC_CONFIG_SERVER_SECTION_TYPE_HMAC, 3 },
34   { "[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       /* Get key length */
344       ret = silc_config_get_token(line, &tmp);
345       if (ret < 0)
346         break;
347       if (ret == 0) {
348         fprintf(stderr, "%s:%d: PKCS key length not defined\n",
349                 config->filename, pc->linenum);
350         break;
351       }
352       config->pkcs->key_len = atoi(tmp);
353       silc_free(tmp);
354
355       check = TRUE;
356       checkmask |= (1L << pc->section->type);
357       break;
358
359     case SILC_CONFIG_SERVER_SECTION_TYPE_HASH_FUNCTION:
360
361       SILC_SERVER_CONFIG_LIST_ALLOC(config->hash_func);
362
363       /* Get Hash function name */
364       ret = silc_config_get_token(line, &config->hash_func->alg_name);
365       if (ret < 0)
366         break;
367       if (ret == 0) {
368         fprintf(stderr, "%s:%d: Hash function name not defined\n",
369                 config->filename, pc->linenum);
370         break;
371       }
372       
373       /* Get Hash function module name */
374       config->hash_func->sim_name = NULL;
375       ret = silc_config_get_token(line, &config->hash_func->sim_name);
376       if (ret < 0)
377         break;
378
379       /* Get block 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 block length not defined\n",
385                 config->filename, pc->linenum);
386         break;
387       }
388       config->hash_func->block_len = atoi(tmp);
389       silc_free(tmp);
390
391       /* Get hash length */
392       ret = silc_config_get_token(line, &tmp);
393       if (ret < 0)
394         break;
395       if (ret == 0) {
396         fprintf(stderr, "%s:%d: Hash function hash length not defined\n",
397                 config->filename, pc->linenum);
398         break;
399       }
400       config->hash_func->key_len = atoi(tmp);
401       silc_free(tmp);
402
403       check = TRUE;
404       checkmask |= (1L << pc->section->type);
405       break;
406
407     case SILC_CONFIG_SERVER_SECTION_TYPE_HMAC:
408
409       SILC_SERVER_CONFIG_LIST_ALLOC(config->hmac);
410
411       /* Get HMAC name */
412       ret = silc_config_get_token(line, &config->hmac->alg_name);
413       if (ret < 0)
414         break;
415       if (ret == 0) {
416         fprintf(stderr, "%s:%d: HMAC name not defined\n",
417                 config->filename, pc->linenum);
418         break;
419       }
420
421       /* Get hash name */
422       ret = silc_config_get_token(line, &config->hmac->sim_name);
423       if (ret < 0)
424         break;
425       if (ret == 0) {
426         fprintf(stderr, "%s:%d: Hash function name not defined\n",
427                 config->filename, pc->linenum);
428         break;
429       }
430       
431       /* Get MAC length */
432       ret = silc_config_get_token(line, &tmp);
433       if (ret < 0)
434         break;
435       if (ret == 0) {
436         fprintf(stderr, "%s:%d: HMAC's MAC length not defined\n",
437                 config->filename, pc->linenum);
438         break;
439       }
440       config->hmac->key_len = atoi(tmp);
441       silc_free(tmp);
442
443       check = TRUE;
444       checkmask |= (1L << pc->section->type);
445       break;
446
447     case SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_KEYS:
448
449       if (!config->server_keys)
450         config->server_keys = silc_calloc(1, sizeof(*config->server_keys));
451
452       ret = silc_config_get_token(line, &tmp);
453       if (ret < 0)
454         break;
455       if (ret == 0) {
456         fprintf(stderr, "%s:%d: Public key name not defined\n",
457                 config->filename, pc->linenum);
458         break;
459       }
460       
461       if (!silc_pkcs_load_public_key(tmp, &config->server_keys->public_key, 
462                                      SILC_PKCS_FILE_PEM))
463         if (!silc_pkcs_load_public_key(tmp, &config->server_keys->public_key, 
464                                        SILC_PKCS_FILE_BIN)) {
465           fprintf(stderr, "%s:%d: Could not load public key file `%s'\n",
466                   config->filename, pc->linenum, tmp);
467           break;
468         }
469       silc_free(tmp);
470
471       ret = silc_config_get_token(line, &tmp);
472       if (ret < 0)
473         break;
474       if (ret == 0) {
475         fprintf(stderr, "%s:%d: Private key name not defined\n",
476                 config->filename, pc->linenum);
477         break;
478       }
479       
480       if (!silc_pkcs_load_private_key(tmp, &config->server_keys->private_key, 
481                                      SILC_PKCS_FILE_BIN))
482         if (!silc_pkcs_load_private_key(tmp, 
483                                         &config->server_keys->private_key, 
484                                         SILC_PKCS_FILE_PEM)) {
485           fprintf(stderr, "%s:%d: Could not load private key file `%s'\n",
486                   config->filename, pc->linenum, tmp);
487           break;
488         }
489       silc_free(tmp);
490
491       check = TRUE;
492       checkmask |= (1L << pc->section->type);
493       break;
494
495     case SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO:
496
497       if (!config->server_info)
498         config->server_info = silc_calloc(1, sizeof(*config->server_info));
499
500       /* Get server name */
501       ret = silc_config_get_token(line, &config->server_info->server_name);
502       if (ret < 0)
503         break;
504       if (ret == 0) {
505         /* Server name not defined */
506
507       }
508       
509       /* Get server IP */
510       ret = silc_config_get_token(line, &config->server_info->server_ip);
511       if (ret < 0)
512         break;
513       if (ret == 0) {
514         /* Server IP not defined */
515
516       }
517
518       /* Get server location */
519       ret = silc_config_get_token(line, &config->server_info->location);
520       if (ret < 0)
521         break;
522
523       /* Get server port */
524       /* XXX: Need port here??? */
525       ret = silc_config_get_token(line, &tmp);
526       if (ret < 0)
527         break;
528       if (ret == 0) {
529         /* Port not defined */
530
531       }
532       config->server_info->port = atoi(tmp);
533       silc_free(tmp);
534
535       check = TRUE;
536       checkmask |= (1L << pc->section->type);
537       break;
538
539     case SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO:
540
541       if (!config->admin_info)
542         config->admin_info = silc_calloc(1, sizeof(*config->admin_info));
543
544       /* Get location */
545       ret = silc_config_get_token(line, &config->admin_info->location);
546       if (ret < 0)
547         break;
548
549       /* Get server type */
550       ret = silc_config_get_token(line, &config->admin_info->server_type);
551       if (ret < 0)
552         break;
553
554       /* Get admins name */
555       ret = silc_config_get_token(line, &config->admin_info->admin_name);
556       if (ret < 0)
557         break;
558
559       /* Get admins email address */
560       ret = silc_config_get_token(line, &config->admin_info->admin_email);
561       if (ret < 0)
562         break;
563
564       check = TRUE;
565       checkmask |= (1L << pc->section->type);
566       break;
567
568     case SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT:
569
570       SILC_SERVER_CONFIG_LIST_ALLOC(config->listen_port);
571
572       /* Get host */
573       ret = silc_config_get_token(line, &config->listen_port->host);
574       if (ret < 0)
575         break;
576
577       /* Get remote IP */
578       ret = silc_config_get_token(line, &config->listen_port->remote_ip);
579       if (ret < 0)
580         break;
581
582       /* Get port */
583       ret = silc_config_get_token(line, &tmp);
584       if (ret < 0)
585         break;
586       if (ret == 0) {
587         /* Any port */
588         config->listen_port->port = 0;
589       } else {
590         config->listen_port->port = atoi(tmp);
591         silc_free(tmp);
592       }
593
594       check = TRUE;
595       checkmask |= (1L << pc->section->type);
596       break;
597
598     case SILC_CONFIG_SERVER_SECTION_TYPE_IDENTITY:
599
600       if (!config->identity)
601         config->identity = silc_calloc(1, sizeof(*config->identity));
602
603       /* Get user */
604       ret = silc_config_get_token(line, &config->identity->user);
605       if (ret < 0)
606         break;
607       /* Get group */
608       ret = silc_config_get_token(line, &config->identity->group);
609       if (ret < 0)
610         break;
611
612       check = TRUE;
613       checkmask |= (1L << pc->section->type);
614
615     case SILC_CONFIG_SERVER_SECTION_TYPE_CONNECTION_CLASS:
616
617       SILC_SERVER_CONFIG_LIST_ALLOC(config->conn_class);
618
619       /* Get class number */
620       ret = silc_config_get_token(line, &tmp);
621       if (ret < 0)
622         break;
623       if (ret == 0) {
624         /* Class number not defined */
625
626       }
627       config->conn_class->class = atoi(tmp);
628       silc_free(tmp);
629
630       /* Get ping frequency */
631       ret = silc_config_get_token(line, &tmp);
632       if (ret < 0)
633         break;
634       config->conn_class->ping_freq = atoi(tmp);
635       silc_free(tmp);
636
637       /* Get connect frequency */
638       ret = silc_config_get_token(line, &tmp);
639       if (ret < 0)
640         break;
641       config->conn_class->connect_freq = atoi(tmp);
642       silc_free(tmp);
643
644       /* Get max links */
645       ret = silc_config_get_token(line, &tmp);
646       if (ret < 0)
647         break;
648       config->conn_class->max_links = atoi(tmp);
649       silc_free(tmp);
650
651       check = TRUE;
652       checkmask |= (1L << pc->section->type);
653       break;
654
655     case SILC_CONFIG_SERVER_SECTION_TYPE_LOGGING:
656
657       SILC_SERVER_CONFIG_LIST_ALLOC(config->logging);
658
659       /* Get log section type and check it */
660       ret = silc_config_get_token(line, &config->logging->logtype);
661       if (ret < 0)
662         break;
663       if (ret == 0) {
664         fprintf(stderr, "%s:%d: Log file section not defined\n", 
665                 config->filename, pc->linenum);
666         break;
667       }
668       if (strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_INFO)
669           && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_WARNING)
670           && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_ERROR)
671           && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
672         fprintf(stderr, "%s:%d: Unknown log file section '%s'\n",
673                 config->filename, pc->linenum, config->logging->logtype);
674         break;
675       }
676
677       /* Get log filename */
678       ret = silc_config_get_token(line, &config->logging->filename);
679       if (ret < 0)
680         break;
681       if (ret == 0) {
682         fprintf(stderr, "%s:%d: Log file name not defined\n",
683                 config->filename, pc->linenum);
684         break;
685       }
686
687       /* Get max byte size */
688       ret = silc_config_get_token(line, &tmp);
689       if (ret < 0)
690         break;
691       if (ret) {
692         config->logging->maxsize = atoi(tmp);
693         silc_free(tmp);
694       }
695
696       check = TRUE;
697       checkmask |= (1L << pc->section->type);
698       break;
699
700     case SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION:
701
702       SILC_SERVER_CONFIG_LIST_ALLOC(config->clients);
703
704       /* Get host */
705       ret = silc_config_get_token(line, &config->clients->host);
706       if (ret < 0)
707         break;
708       if (ret == 0)
709         /* Any host */
710         config->clients->host = strdup("*");
711
712       /* Get authentication method */
713       ret = silc_config_get_token(line, &tmp);
714       if (ret < 0)
715         break;
716       if (ret) {
717         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
718             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
719           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
720                   config->filename, pc->linenum, tmp);
721           break;
722         }
723
724         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
725           config->clients->auth_meth = SILC_AUTH_PASSWORD;
726
727         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
728           config->clients->auth_meth = SILC_AUTH_PUBLIC_KEY;
729
730         silc_free(tmp);
731       }
732
733       /* Get authentication data */
734       ret = silc_config_get_token(line, (char **)&config->clients->auth_data);
735       if (ret < 0)
736         break;
737
738       if (config->clients->auth_meth == SILC_AUTH_PASSWORD) {
739         config->clients->auth_data_len = strlen(config->clients->auth_data);
740       } else if (config->clients->auth_meth == SILC_AUTH_PUBLIC_KEY) {
741         /* Get the public key */
742         SilcPublicKey public_key;
743
744         if (!silc_pkcs_load_public_key(config->clients->auth_data,
745                                        &public_key, SILC_PKCS_FILE_PEM))
746           if (!silc_pkcs_load_public_key(config->clients->auth_data,
747                                          &public_key, SILC_PKCS_FILE_BIN)) {
748             fprintf(stderr, "%s:%d: Could not load public key file `%s'\n",
749                     config->filename, pc->linenum, 
750                     (char *)config->clients->auth_data);
751             break;
752           }
753
754         silc_free(config->clients->auth_data);
755         config->clients->auth_data = (void *)public_key;
756         config->clients->auth_data_len = 0;
757       }
758
759       /* Get port */
760       ret = silc_config_get_token(line, &tmp);
761       if (ret < 0)
762         break;
763       if (ret) {
764         config->clients->port = atoi(tmp);
765         silc_free(tmp);
766       }
767
768       /* Get class number */
769       ret = silc_config_get_token(line, &tmp);
770       if (ret < 0)
771         break;
772       if (ret) {
773         config->clients->class = atoi(tmp);
774         silc_free(tmp);
775       }
776
777       check = TRUE;
778       checkmask |= (1L << pc->section->type);
779       break;
780
781     case SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION:
782
783       SILC_SERVER_CONFIG_LIST_ALLOC(config->servers);
784
785       /* Get host */
786       ret = silc_config_get_token(line, &config->servers->host);
787       if (ret < 0)
788         break;
789       if (ret == 0)
790         /* Any host */
791         config->servers->host = strdup("*");
792
793       /* Get authentication method */
794       ret = silc_config_get_token(line, &tmp);
795       if (ret < 0)
796         break;
797       if (ret) {
798         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
799             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
800           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
801                   config->filename, pc->linenum, tmp);
802           break;
803         }
804
805         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
806           config->servers->auth_meth = SILC_AUTH_PASSWORD;
807
808         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
809           config->servers->auth_meth = SILC_AUTH_PUBLIC_KEY;
810
811         silc_free(tmp);
812       }
813
814       /* Get authentication data */
815       ret = silc_config_get_token(line, (char **)&config->servers->auth_data);
816       if (ret < 0)
817         break;
818
819       if (config->servers->auth_meth == SILC_AUTH_PASSWORD) {
820         config->servers->auth_data_len = strlen(config->servers->auth_data);
821       } else if (config->servers->auth_meth == SILC_AUTH_PUBLIC_KEY) {
822         /* Get the public key */
823         SilcPublicKey public_key;
824
825         if (!silc_pkcs_load_public_key(config->servers->auth_data,
826                                        &public_key, SILC_PKCS_FILE_PEM))
827           if (!silc_pkcs_load_public_key(config->servers->auth_data,
828                                          &public_key, SILC_PKCS_FILE_BIN)) {
829             fprintf(stderr, "%s:%d: Could not load public key file `%s'\n",
830                     config->filename, pc->linenum, 
831                     (char *)config->servers->auth_data);
832             break;
833           }
834
835         silc_free(config->servers->auth_data);
836         config->servers->auth_data = (void *)public_key;
837         config->servers->auth_data_len = 0;
838       }
839
840       /* Get port */
841       ret = silc_config_get_token(line, &tmp);
842       if (ret < 0)
843         break;
844       if (ret) {
845         config->servers->port = atoi(tmp);
846         silc_free(tmp);
847       }
848
849       /* Get version */
850       ret = silc_config_get_token(line, &config->servers->version);
851       if (ret < 0)
852         break;
853
854       /* Get class number */
855       ret = silc_config_get_token(line, &tmp);
856       if (ret < 0)
857         break;
858       if (ret) {
859         config->servers->class = atoi(tmp);
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       //      if (ret == 0)
876       ///* Any host */
877       //        config->routers->host = strdup("*");
878
879       /* Get authentication method */
880       ret = silc_config_get_token(line, &tmp);
881       if (ret < 0)
882         break;
883       if (ret) {
884         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
885             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
886           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
887                   config->filename, pc->linenum, tmp);
888           break;
889         }
890
891         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
892           config->routers->auth_meth = SILC_AUTH_PASSWORD;
893
894         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
895           config->routers->auth_meth = SILC_AUTH_PUBLIC_KEY;
896
897         silc_free(tmp);
898       }
899
900       /* Get authentication data */
901       ret = silc_config_get_token(line, (char **)&config->routers->auth_data);
902       if (ret < 0)
903         break;
904
905       if (config->routers->auth_meth == SILC_AUTH_PASSWORD) {
906         config->routers->auth_data_len = strlen(config->routers->auth_data);
907       } else if (config->routers->auth_meth == SILC_AUTH_PUBLIC_KEY) {
908         /* Get the public key */
909         SilcPublicKey public_key;
910
911         if (!silc_pkcs_load_public_key(config->routers->auth_data,
912                                        &public_key, SILC_PKCS_FILE_PEM))
913           if (!silc_pkcs_load_public_key(config->routers->auth_data,
914                                          &public_key, SILC_PKCS_FILE_BIN)) {
915             fprintf(stderr, "%s:%d: Could not load public key file `%s'\n",
916                     config->filename, pc->linenum, 
917                     (char *)config->routers->auth_data);
918             break;
919           }
920
921         silc_free(config->routers->auth_data);
922         config->routers->auth_data = (void *)public_key;
923         config->routers->auth_data_len = 0;
924       }
925
926       /* Get port */
927       ret = silc_config_get_token(line, &tmp);
928       if (ret < 0)
929         break;
930       if (ret) {
931         config->routers->port = atoi(tmp);
932         silc_free(tmp);
933       }
934
935       /* Get version */
936       ret = silc_config_get_token(line, &config->routers->version);
937       if (ret < 0)
938         break;
939
940       /* Get class number */
941       ret = silc_config_get_token(line, &tmp);
942       if (ret < 0)
943         break;
944       if (ret) {
945         config->routers->class = atoi(tmp);
946         silc_free(tmp);
947       }
948
949       /* Get whether we are initiator or not */
950       ret = silc_config_get_token(line, &tmp);
951       if (ret < 0)
952         break;
953       if (ret) {
954         config->routers->initiator = atoi(tmp);
955         if (config->routers->initiator != 0)
956           config->routers->initiator = TRUE;
957         silc_free(tmp);
958       }
959
960       check = TRUE;
961       checkmask |= (1L << pc->section->type);
962       break;
963
964     case SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_CONNECTION:
965
966       SILC_SERVER_CONFIG_LIST_ALLOC(config->admins);
967
968       /* Get host */
969       ret = silc_config_get_token(line, &config->admins->host);
970       if (ret < 0)
971         break;
972       if (ret == 0)
973         /* Any host */
974         config->admins->host = strdup("*");
975
976       /* Get username */
977       ret = silc_config_get_token(line, &config->admins->username);
978       if (ret < 0)
979         break;
980       if (ret == 0)
981         /* Any username */
982         config->admins->username = strdup("*");
983
984       /* Get nickname */
985       ret = silc_config_get_token(line, &config->admins->nickname);
986       if (ret < 0)
987         break;
988       if (ret == 0)
989         /* Any nickname */
990         config->admins->nickname = strdup("*");
991
992       /* Get authentication method */
993       ret = silc_config_get_token(line, &tmp);
994       if (ret < 0)
995         break;
996       if (ret) {
997         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
998             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
999           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
1000                   config->filename, pc->linenum, tmp);
1001           break;
1002         }
1003
1004         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
1005           config->admins->auth_meth = SILC_AUTH_PASSWORD;
1006
1007         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
1008           config->admins->auth_meth = SILC_AUTH_PUBLIC_KEY;
1009
1010         silc_free(tmp);
1011       }
1012
1013       /* Get authentication data */
1014       ret = silc_config_get_token(line, (char **)&config->admins->auth_data);
1015       if (ret < 0)
1016         break;
1017
1018       if (config->admins->auth_meth == SILC_AUTH_PASSWORD) {
1019         config->admins->auth_data_len = strlen(config->admins->auth_data);
1020       } else if (config->admins->auth_meth == SILC_AUTH_PUBLIC_KEY) {
1021         /* Get the public key */
1022         SilcPublicKey public_key;
1023
1024         if (!silc_pkcs_load_public_key(config->admins->auth_data,
1025                                        &public_key, SILC_PKCS_FILE_PEM))
1026           if (!silc_pkcs_load_public_key(config->admins->auth_data,
1027                                          &public_key, SILC_PKCS_FILE_BIN)) {
1028             fprintf(stderr, "%s:%d: Could not load public key file `%s'\n",
1029                     config->filename, pc->linenum, 
1030                     (char *)config->admins->auth_data);
1031             break;
1032           }
1033
1034         silc_free(config->admins->auth_data);
1035         config->admins->auth_data = (void *)public_key;
1036         config->admins->auth_data_len = 0;
1037       }
1038
1039       check = TRUE;
1040       checkmask |= (1L << pc->section->type);
1041       break;
1042
1043     case SILC_CONFIG_SERVER_SECTION_TYPE_DENY_CONNECTION:
1044
1045       SILC_SERVER_CONFIG_LIST_ALLOC(config->denied);
1046
1047       /* Get host */
1048       ret = silc_config_get_token(line, &config->denied->host);
1049       if (ret < 0)
1050         break;
1051       if (ret == 0) {
1052         /* Any host */
1053         config->denied->host = strdup("*");
1054         fprintf(stderr, "warning: %s:%d: Denying all connections",
1055                 config->filename, pc->linenum);
1056       }
1057
1058       /* Get port */
1059       ret = silc_config_get_token(line, &tmp);
1060       if (ret < 0)
1061         break;
1062       if (ret == 0) {
1063         /* Any port */
1064         config->denied->port = 0;
1065       } else {
1066         config->denied->port = atoi(tmp);
1067         silc_free(tmp);
1068       }
1069
1070       /* Get comment */
1071       ret = silc_config_get_token(line, &config->denied->comment);
1072       if (ret < 0)
1073         break;
1074
1075       check = TRUE;
1076       checkmask |= (1L << pc->section->type);
1077       break;
1078
1079     case SILC_CONFIG_SERVER_SECTION_TYPE_MOTD:
1080
1081       if (!config->motd)
1082         config->motd = silc_calloc(1, sizeof(*config->motd));
1083
1084       /* Get motd file */
1085       ret = silc_config_get_token(line, &config->motd->motd_file);
1086       if (ret < 0)
1087         break;
1088
1089       check = TRUE;
1090       checkmask |= (1L << pc->section->type);
1091       break;
1092
1093     case SILC_CONFIG_SERVER_SECTION_TYPE_NONE:
1094     default:
1095       /* Error */
1096       break;
1097     }
1098
1099     /* Check for error */
1100     if (check == FALSE) {
1101       /* Line could not be parsed */
1102       fprintf(stderr, "%s:%d: Parse error\n", config->filename, pc->linenum);
1103       break;
1104     }
1105
1106     pc = pc->next;
1107   }
1108
1109   if (check == FALSE)
1110     return FALSE;;
1111
1112   /* Check that all mandatory sections really were found. If not, the server
1113      cannot function and we return error. */
1114   ret = silc_server_config_check_sections(checkmask);
1115   if (ret == FALSE) {
1116     /* XXX */
1117
1118   }
1119   
1120   /* Before returning all the lists in the config object must be set
1121      to their first values (the last value is first here). */
1122   while (config->cipher && config->cipher->prev)
1123     config->cipher = config->cipher->prev;
1124   while (config->pkcs && config->pkcs->prev)
1125     config->pkcs = config->pkcs->prev;
1126   while (config->hash_func && config->hash_func->prev)
1127     config->hash_func = config->hash_func->prev;
1128   while (config->hmac && config->hmac->prev)
1129     config->hmac = config->hmac->prev;
1130   while (config->listen_port && config->listen_port->prev)
1131     config->listen_port = config->listen_port->prev;
1132   while (config->logging && config->logging->prev)
1133     config->logging = config->logging->prev;
1134   while (config->conn_class && config->conn_class->prev)
1135     config->conn_class = config->conn_class->prev;
1136   while (config->clients && config->clients->prev)
1137     config->clients = config->clients->prev;
1138   while (config->servers && config->servers->prev)
1139     config->servers = config->servers->prev;
1140   while (config->admins && config->admins->prev)
1141     config->admins = config->admins->prev;
1142   while (config->routers && config->routers->prev)
1143     config->routers = config->routers->prev;
1144   
1145   SILC_LOG_DEBUG(("Done"));
1146   
1147   return TRUE;
1148 }
1149
1150 /* This function checks that the mask sent as argument includes all the 
1151    sections that are mandatory in SILC server. */
1152
1153 int silc_server_config_check_sections(uint32 checkmask)
1154 {
1155   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO))) {
1156     
1157     return FALSE;
1158   }
1159   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO))) {
1160     
1161     return FALSE;
1162   }
1163   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT))) {
1164     
1165     return FALSE;
1166   }
1167   if (!(checkmask & 
1168         (1L << SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION))) {
1169     
1170     return FALSE;
1171   }
1172   if (!(checkmask 
1173         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION))) {
1174     
1175     return FALSE;
1176   }
1177   if (!(checkmask 
1178         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION))) {
1179     
1180     return FALSE;
1181   }
1182
1183   return TRUE;
1184 }
1185
1186 /* Sets log files where log messages is saved by the server. */
1187
1188 void silc_server_config_setlogfiles(SilcServerConfig config)
1189 {
1190   SilcServerConfigSectionLogging *log;
1191   char *info, *warning, *error, *fatal;
1192   uint32 info_size, warning_size, error_size, fatal_size;
1193
1194   SILC_LOG_DEBUG(("Setting configured log file names"));
1195
1196   /* Set default files before checking configuration */
1197   info = SILC_LOG_FILE_INFO;
1198   warning = SILC_LOG_FILE_WARNING;
1199   error = SILC_LOG_FILE_ERROR;
1200   fatal = SILC_LOG_FILE_FATAL;
1201   info_size = 0;
1202   warning_size = 0;
1203   error_size = 0;
1204   fatal_size = 0;
1205
1206   log = config->logging;
1207   while(log) {
1208     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_INFO)) {
1209       info = log->filename;
1210       info_size = log->maxsize;
1211     }
1212     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_WARNING)) {
1213       warning = log->filename;
1214       warning_size = log->maxsize;
1215     }
1216     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_ERROR)) {
1217       error = log->filename;
1218       error_size = log->maxsize;
1219     }
1220     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
1221       fatal = log->filename;
1222       fatal_size = log->maxsize;
1223     }
1224
1225     log = log->next;
1226   }
1227
1228   silc_log_set_files(info, info_size, warning, warning_size,
1229                      error, error_size, fatal, fatal_size);
1230 }
1231
1232 /* Registers configured ciphers. These can then be allocated by the
1233    server when needed. */
1234
1235 void silc_server_config_register_ciphers(SilcServerConfig config)
1236 {
1237   SilcServerConfigSectionAlg *alg;
1238   SilcServer server = (SilcServer)config->server;
1239
1240   SILC_LOG_DEBUG(("Registering configured ciphers"));
1241
1242   alg = config->cipher;
1243   while(alg) {
1244
1245     if (!alg->sim_name) {
1246       /* Crypto module is supposed to be built in. Nothing to be done
1247          here except to test that the cipher really is built in. */
1248       SilcCipher tmp = NULL;
1249
1250       if (silc_cipher_alloc(alg->alg_name, &tmp) == FALSE) {
1251         SILC_LOG_ERROR(("Unsupported cipher `%s'", alg->alg_name));
1252         silc_server_stop(server);
1253         exit(1);
1254       }
1255       silc_cipher_free(tmp);
1256
1257 #ifdef SILC_SIM
1258     } else {
1259       /* Load (try at least) the crypto SIM module */
1260       SilcCipherObject cipher;
1261       SilcSimContext *sim;
1262       char *alg_name;
1263
1264       memset(&cipher, 0, sizeof(cipher));
1265       cipher.name = alg->alg_name;
1266       cipher.block_len = alg->block_len;
1267       cipher.key_len = alg->key_len * 8;
1268
1269       sim = silc_sim_alloc();
1270       sim->type = SILC_SIM_CIPHER;
1271       sim->libname = alg->sim_name;
1272
1273       alg_name = strdup(alg->alg_name);
1274       if (strchr(alg_name, '-'))
1275         *strchr(alg_name, '-') = '\0';
1276
1277       if ((silc_sim_load(sim))) {
1278         cipher.set_key = 
1279           silc_sim_getsym(sim, silc_sim_symname(alg_name, 
1280                                                 SILC_CIPHER_SIM_SET_KEY));
1281         SILC_LOG_DEBUG(("set_key=%p", cipher.set_key));
1282         cipher.set_key_with_string = 
1283           silc_sim_getsym(sim, silc_sim_symname(alg_name, 
1284                                                 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1285         SILC_LOG_DEBUG(("set_key_with_string=%p", cipher.set_key_with_string));
1286         cipher.encrypt = 
1287           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1288                                                 SILC_CIPHER_SIM_ENCRYPT_CBC));
1289         SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher.encrypt));
1290         cipher.decrypt = 
1291           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1292                                                 SILC_CIPHER_SIM_DECRYPT_CBC));
1293         SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher.decrypt));
1294         cipher.context_len = 
1295           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1296                                                 SILC_CIPHER_SIM_CONTEXT_LEN));
1297         SILC_LOG_DEBUG(("context_len=%p", cipher.context_len));
1298
1299         /* Put the SIM to the list of all SIM's in server */
1300         silc_dlist_add(server->sim, sim);
1301
1302         silc_free(alg_name);
1303       } else {
1304         SILC_LOG_ERROR(("Error configuring ciphers"));
1305         silc_server_stop(server);
1306         exit(1);
1307       }
1308
1309       /* Register the cipher */
1310       silc_cipher_register(&cipher);
1311 #endif
1312     }
1313
1314     alg = alg->next;
1315   }
1316 }
1317
1318 /* Registers configured PKCS's. */
1319 /* XXX: This really doesn't do anything now since we have statically
1320    registered our PKCS's. This should be implemented when PKCS works
1321    as SIM's. This checks now only that the PKCS user requested is 
1322    really out there. */
1323
1324 void silc_server_config_register_pkcs(SilcServerConfig config)
1325 {
1326   SilcServerConfigSectionAlg *alg = config->pkcs;
1327   SilcServer server = (SilcServer)config->server;
1328   SilcPKCS tmp = NULL;
1329
1330   SILC_LOG_DEBUG(("Registering configured PKCS"));
1331
1332   while(alg) {
1333
1334     if (silc_pkcs_alloc(alg->alg_name, &tmp) == FALSE) {
1335       SILC_LOG_ERROR(("Unsupported PKCS `%s'", alg->alg_name));
1336       silc_server_stop(server);
1337       exit(1);
1338     }
1339     silc_free(tmp);
1340
1341     alg = alg->next;
1342   }
1343 }
1344
1345 /* Registers configured hash functions. These can then be allocated by the
1346    server when needed. */
1347
1348 void silc_server_config_register_hashfuncs(SilcServerConfig config)
1349 {
1350   SilcServerConfigSectionAlg *alg;
1351   SilcServer server = (SilcServer)config->server;
1352
1353   SILC_LOG_DEBUG(("Registering configured hash functions"));
1354
1355   alg = config->hash_func;
1356   while(alg) {
1357
1358     if (!alg->sim_name) {
1359       /* Hash module is supposed to be built in. Nothing to be done
1360          here except to test that the hash function really is built in. */
1361       SilcHash tmp = NULL;
1362
1363       if (silc_hash_alloc(alg->alg_name, &tmp) == FALSE) {
1364         SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->alg_name));
1365         silc_server_stop(server);
1366         exit(1);
1367       }
1368       silc_hash_free(tmp);
1369
1370 #ifdef SILC_SIM
1371     } else {
1372       /* Load (try at least) the hash SIM module */
1373       SilcHashObject hash;
1374       SilcSimContext *sim;
1375
1376       memset(&hash, 0, sizeof(hash));
1377       hash.name = alg->alg_name;
1378       hash.block_len = alg->block_len;
1379       hash.hash_len = alg->key_len;
1380
1381       sim = silc_sim_alloc();
1382       sim->type = SILC_SIM_HASH;
1383       sim->libname = alg->sim_name;
1384
1385       if ((silc_sim_load(sim))) {
1386         hash.init = 
1387           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name, 
1388                                                 SILC_HASH_SIM_INIT));
1389         SILC_LOG_DEBUG(("init=%p", hash.init));
1390         hash.update = 
1391           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1392                                                 SILC_HASH_SIM_UPDATE));
1393         SILC_LOG_DEBUG(("update=%p", hash.update));
1394         hash.final = 
1395           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1396                                                 SILC_HASH_SIM_FINAL));
1397         SILC_LOG_DEBUG(("final=%p", hash.final));
1398         hash.context_len = 
1399           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1400                                                 SILC_HASH_SIM_CONTEXT_LEN));
1401         SILC_LOG_DEBUG(("context_len=%p", hash.context_len));
1402
1403         /* Put the SIM to the table of all SIM's in server */
1404         silc_dlist_add(server->sim, sim);
1405       } else {
1406         SILC_LOG_ERROR(("Error configuring hash functions"));
1407         silc_server_stop(server);
1408         exit(1);
1409       }
1410
1411       /* Register the hash function */
1412       silc_hash_register(&hash);
1413 #endif
1414     }
1415
1416     alg = alg->next;
1417   }
1418 }
1419
1420 /* Registers configure HMACs. These can then be allocated by the server
1421    when needed. */
1422
1423 void silc_server_config_register_hmacs(SilcServerConfig config)
1424 {
1425   SilcServerConfigSectionAlg *alg;
1426   SilcServer server = (SilcServer)config->server;
1427
1428   SILC_LOG_DEBUG(("Registering configured HMACs"));
1429
1430   if (!config->hmac) {
1431     SILC_LOG_ERROR(("HMACs are not configured. SILC cannot work without "
1432                     "HMACs"));
1433     silc_server_stop(server);
1434     exit(1);
1435   }
1436
1437   alg = config->hmac;
1438   while(alg) {
1439     SilcHmacObject hmac;
1440     
1441     if (!silc_hash_is_supported(alg->sim_name)) {
1442       SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->sim_name));
1443       silc_server_stop(server);
1444       exit(1);
1445     }
1446     
1447     /* Register the HMAC */
1448     memset(&hmac, 0, sizeof(hmac));
1449     hmac.name = alg->alg_name;
1450     hmac.len = alg->key_len;
1451     silc_hmac_register(&hmac);
1452
1453     alg = alg->next;
1454   }
1455 }
1456
1457 /* Returns client authentication information from server configuration
1458    by host (name or ip). If `port' is non-null then both name or IP and 
1459    the port must match. */
1460
1461 SilcServerConfigSectionClientConnection *
1462 silc_server_config_find_client_conn(SilcServerConfig config, 
1463                                     char *host, int port)
1464 {
1465   int i;
1466   SilcServerConfigSectionClientConnection *client = NULL;
1467   bool match = FALSE;
1468
1469   if (!host)
1470     return NULL;
1471
1472   if (!config->clients)
1473     return NULL;
1474
1475   client = config->clients;
1476
1477   for (i = 0; client; i++) {
1478     if (silc_string_compare(client->host, host))
1479       match = TRUE;
1480
1481     if (port && client->port && client->port != port)
1482       match = FALSE;
1483
1484     if (match)
1485       break;
1486
1487     client = client->next;
1488   }
1489
1490   if (!client)
1491     return NULL;
1492
1493   return client;
1494 }
1495
1496 /* Returns server connection info from server configuartion by host 
1497    (name or ip). If `port' is non-null then both name or IP and the port
1498    must match. */
1499
1500 SilcServerConfigSectionServerConnection *
1501 silc_server_config_find_server_conn(SilcServerConfig config, 
1502                                     char *host, int port)
1503 {
1504   int i;
1505   SilcServerConfigSectionServerConnection *serv = NULL;
1506   bool match = FALSE;
1507
1508   if (!host)
1509     return NULL;
1510
1511   if (!config->servers)
1512     return NULL;
1513
1514   serv = config->servers;
1515   for (i = 0; serv; i++) {
1516     if (silc_string_compare(serv->host, host))
1517       match = TRUE;
1518
1519     if (port && serv->port && serv->port != port)
1520       match = FALSE;
1521
1522     if (match)
1523       break;
1524
1525     serv = serv->next;
1526   }
1527
1528   if (!serv)
1529     return NULL;
1530
1531   return serv;
1532 }
1533
1534 /* Returns router connection info from server configuartion by
1535    host (name or ip). */
1536
1537 SilcServerConfigSectionServerConnection *
1538 silc_server_config_find_router_conn(SilcServerConfig config, 
1539                                     char *host, int port)
1540 {
1541   int i;
1542   SilcServerConfigSectionServerConnection *serv = NULL;
1543   bool match = FALSE;
1544
1545   if (!host)
1546     return NULL;
1547
1548   if (!config->routers)
1549     return NULL;
1550
1551   serv = config->routers;
1552   for (i = 0; serv; i++) {
1553     if (silc_string_compare(serv->host, host))
1554       match = TRUE;
1555
1556     if (port && serv->port && serv->port != port)
1557       match = FALSE;
1558
1559     if (match)
1560       break;
1561
1562     serv = serv->next;
1563   }
1564
1565   if (!serv)
1566     return NULL;
1567
1568   return serv;
1569 }
1570
1571 /* Returns TRUE if configuartion for a router connection that we are 
1572    initiating exists. */
1573
1574 bool silc_server_config_is_primary_route(SilcServerConfig config)
1575 {
1576   int i;
1577   SilcServerConfigSectionServerConnection *serv = NULL;
1578   bool found = FALSE;
1579
1580   serv = config->routers;
1581   for (i = 0; serv; i++) {
1582     if (serv->initiator == TRUE) {
1583       found = TRUE;
1584       break;
1585     }
1586
1587     serv = serv->next;
1588   }
1589
1590   return found;
1591 }
1592
1593 /* Returns Admin connection configuration by host, username and/or 
1594    nickname. */
1595
1596 SilcServerConfigSectionAdminConnection *
1597 silc_server_config_find_admin(SilcServerConfig config,
1598                               char *host, char *username, char *nickname)
1599 {
1600   SilcServerConfigSectionAdminConnection *admin = NULL;
1601   int i;
1602
1603   if (!config->admins)
1604     return NULL;
1605
1606   if (!host)
1607     host = "*";
1608   if (!username)
1609     username = "*";
1610   if (!nickname)
1611     nickname = "*";
1612
1613   admin = config->admins;
1614   for (i = 0; admin; i++) {
1615     if (silc_string_compare(admin->host, host) &&
1616         silc_string_compare(admin->username, username) &&
1617         silc_string_compare(admin->nickname, nickname))
1618       break;
1619
1620     admin = admin->next;
1621   }
1622
1623   if (!admin)
1624     return NULL;
1625
1626   return admin;
1627 }
1628
1629 /* Returns the Denied connection configuration by host and port. */
1630
1631 SilcServerConfigSectionDenyConnection *
1632 silc_server_config_denied_conn(SilcServerConfig config, char *host,
1633                                int port)
1634 {
1635   int i;
1636   SilcServerConfigSectionDenyConnection *deny = NULL;
1637   bool match = FALSE;
1638
1639   if (!host)
1640     return NULL;
1641
1642   if (!config->denied)
1643     return NULL;
1644
1645   deny = config->denied;
1646   for (i = 0; deny; i++) {
1647     if (silc_string_compare(deny->host, host))
1648       match = TRUE;
1649
1650     if (port && deny->port && deny->port != port)
1651       match = FALSE;
1652
1653     if (match)
1654       break;
1655
1656     deny = deny->next;
1657   }
1658
1659   if (!deny)
1660     return NULL;
1661
1662   return deny;
1663 }