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