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, 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, 4 },
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       /* Not implemented yet */
1045       check = TRUE;
1046       break;
1047
1048     case SILC_CONFIG_SERVER_SECTION_TYPE_MOTD:
1049
1050       if (!config->motd)
1051         config->motd = silc_calloc(1, sizeof(*config->motd));
1052
1053       /* Get motd file */
1054       ret = silc_config_get_token(line, &config->motd->motd_file);
1055       if (ret < 0)
1056         break;
1057
1058       check = TRUE;
1059       checkmask |= (1L << pc->section->type);
1060       break;
1061
1062     case SILC_CONFIG_SERVER_SECTION_TYPE_NONE:
1063     default:
1064       /* Error */
1065       break;
1066     }
1067
1068     /* Check for error */
1069     if (check == FALSE) {
1070       /* Line could not be parsed */
1071       fprintf(stderr, "%s:%d: Parse error\n", config->filename, pc->linenum);
1072       break;
1073     }
1074
1075     pc = pc->next;
1076   }
1077
1078   if (check == FALSE)
1079     return FALSE;;
1080
1081   /* Check that all mandatory sections really were found. If not, the server
1082      cannot function and we return error. */
1083   ret = silc_server_config_check_sections(checkmask);
1084   if (ret == FALSE) {
1085     /* XXX */
1086
1087   }
1088   
1089   /* Before returning all the lists in the config object must be set
1090      to their first values (the last value is first here). */
1091   while (config->cipher && config->cipher->prev)
1092     config->cipher = config->cipher->prev;
1093   while (config->pkcs && config->pkcs->prev)
1094     config->pkcs = config->pkcs->prev;
1095   while (config->hash_func && config->hash_func->prev)
1096     config->hash_func = config->hash_func->prev;
1097   while (config->hmac && config->hmac->prev)
1098     config->hmac = config->hmac->prev;
1099   while (config->listen_port && config->listen_port->prev)
1100     config->listen_port = config->listen_port->prev;
1101   while (config->logging && config->logging->prev)
1102     config->logging = config->logging->prev;
1103   while (config->conn_class && config->conn_class->prev)
1104     config->conn_class = config->conn_class->prev;
1105   while (config->clients && config->clients->prev)
1106     config->clients = config->clients->prev;
1107   while (config->servers && config->servers->prev)
1108     config->servers = config->servers->prev;
1109   while (config->admins && config->admins->prev)
1110     config->admins = config->admins->prev;
1111   while (config->routers && config->routers->prev)
1112     config->routers = config->routers->prev;
1113   
1114   SILC_LOG_DEBUG(("Done"));
1115   
1116   return TRUE;
1117 }
1118
1119 /* This function checks that the mask sent as argument includes all the 
1120    sections that are mandatory in SILC server. */
1121
1122 int silc_server_config_check_sections(uint32 checkmask)
1123 {
1124   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO))) {
1125     
1126     return FALSE;
1127   }
1128   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO))) {
1129     
1130     return FALSE;
1131   }
1132   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT))) {
1133     
1134     return FALSE;
1135   }
1136   if (!(checkmask & 
1137         (1L << SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION))) {
1138     
1139     return FALSE;
1140   }
1141   if (!(checkmask 
1142         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION))) {
1143     
1144     return FALSE;
1145   }
1146   if (!(checkmask 
1147         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION))) {
1148     
1149     return FALSE;
1150   }
1151
1152   return TRUE;
1153 }
1154
1155 /* Sets log files where log messages is saved by the server. */
1156
1157 void silc_server_config_setlogfiles(SilcServerConfig config)
1158 {
1159   SilcServerConfigSectionLogging *log;
1160   char *info, *warning, *error, *fatal;
1161   uint32 info_size, warning_size, error_size, fatal_size;
1162
1163   SILC_LOG_DEBUG(("Setting configured log file names"));
1164
1165   /* Set default files before checking configuration */
1166   info = SILC_LOG_FILE_INFO;
1167   warning = SILC_LOG_FILE_WARNING;
1168   error = SILC_LOG_FILE_ERROR;
1169   fatal = SILC_LOG_FILE_FATAL;
1170   info_size = 0;
1171   warning_size = 0;
1172   error_size = 0;
1173   fatal_size = 0;
1174
1175   log = config->logging;
1176   while(log) {
1177     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_INFO)) {
1178       info = log->filename;
1179       info_size = log->maxsize;
1180     }
1181     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_WARNING)) {
1182       warning = log->filename;
1183       warning_size = log->maxsize;
1184     }
1185     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_ERROR)) {
1186       error = log->filename;
1187       error_size = log->maxsize;
1188     }
1189     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
1190       fatal = log->filename;
1191       fatal_size = log->maxsize;
1192     }
1193
1194     log = log->next;
1195   }
1196
1197   silc_log_set_files(info, info_size, warning, warning_size,
1198                      error, error_size, fatal, fatal_size);
1199 }
1200
1201 /* Registers configured ciphers. These can then be allocated by the
1202    server when needed. */
1203
1204 void silc_server_config_register_ciphers(SilcServerConfig config)
1205 {
1206   SilcServerConfigSectionAlg *alg;
1207   SilcServer server = (SilcServer)config->server;
1208
1209   SILC_LOG_DEBUG(("Registering configured ciphers"));
1210
1211   alg = config->cipher;
1212   while(alg) {
1213
1214     if (!alg->sim_name) {
1215       /* Crypto module is supposed to be built in. Nothing to be done
1216          here except to test that the cipher really is built in. */
1217       SilcCipher tmp = NULL;
1218
1219       if (silc_cipher_alloc(alg->alg_name, &tmp) == FALSE) {
1220         SILC_LOG_ERROR(("Unsupported cipher `%s'", alg->alg_name));
1221         silc_server_stop(server);
1222         exit(1);
1223       }
1224       silc_cipher_free(tmp);
1225
1226 #ifdef SILC_SIM
1227     } else {
1228       /* Load (try at least) the crypto SIM module */
1229       SilcCipherObject cipher;
1230       SilcSimContext *sim;
1231       char *alg_name;
1232
1233       memset(&cipher, 0, sizeof(cipher));
1234       cipher.name = alg->alg_name;
1235       cipher.block_len = alg->block_len;
1236       cipher.key_len = alg->key_len * 8;
1237
1238       sim = silc_sim_alloc();
1239       sim->type = SILC_SIM_CIPHER;
1240       sim->libname = alg->sim_name;
1241
1242       alg_name = strdup(alg->alg_name);
1243       if (strchr(alg_name, '-'))
1244         *strchr(alg_name, '-') = '\0';
1245
1246       if ((silc_sim_load(sim))) {
1247         cipher.set_key = 
1248           silc_sim_getsym(sim, silc_sim_symname(alg_name, 
1249                                                 SILC_CIPHER_SIM_SET_KEY));
1250         SILC_LOG_DEBUG(("set_key=%p", cipher.set_key));
1251         cipher.set_key_with_string = 
1252           silc_sim_getsym(sim, silc_sim_symname(alg_name, 
1253                                                 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1254         SILC_LOG_DEBUG(("set_key_with_string=%p", cipher.set_key_with_string));
1255         cipher.encrypt = 
1256           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1257                                                 SILC_CIPHER_SIM_ENCRYPT_CBC));
1258         SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher.encrypt));
1259         cipher.decrypt = 
1260           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1261                                                 SILC_CIPHER_SIM_DECRYPT_CBC));
1262         SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher.decrypt));
1263         cipher.context_len = 
1264           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1265                                                 SILC_CIPHER_SIM_CONTEXT_LEN));
1266         SILC_LOG_DEBUG(("context_len=%p", cipher.context_len));
1267
1268         /* Put the SIM to the list of all SIM's in server */
1269         silc_dlist_add(server->sim, sim);
1270
1271         silc_free(alg_name);
1272       } else {
1273         SILC_LOG_ERROR(("Error configuring ciphers"));
1274         silc_server_stop(server);
1275         exit(1);
1276       }
1277
1278       /* Register the cipher */
1279       silc_cipher_register(&cipher);
1280 #endif
1281     }
1282
1283     alg = alg->next;
1284   }
1285 }
1286
1287 /* Registers configured PKCS's. */
1288 /* XXX: This really doesn't do anything now since we have statically
1289    registered our PKCS's. This should be implemented when PKCS works
1290    as SIM's. This checks now only that the PKCS user requested is 
1291    really out there. */
1292
1293 void silc_server_config_register_pkcs(SilcServerConfig config)
1294 {
1295   SilcServerConfigSectionAlg *alg = config->pkcs;
1296   SilcServer server = (SilcServer)config->server;
1297   SilcPKCS tmp = NULL;
1298
1299   SILC_LOG_DEBUG(("Registering configured PKCS"));
1300
1301   while(alg) {
1302
1303     if (silc_pkcs_alloc(alg->alg_name, &tmp) == FALSE) {
1304       SILC_LOG_ERROR(("Unsupported PKCS `%s'", alg->alg_name));
1305       silc_server_stop(server);
1306       exit(1);
1307     }
1308     silc_free(tmp);
1309
1310     alg = alg->next;
1311   }
1312 }
1313
1314 /* Registers configured hash functions. These can then be allocated by the
1315    server when needed. */
1316
1317 void silc_server_config_register_hashfuncs(SilcServerConfig config)
1318 {
1319   SilcServerConfigSectionAlg *alg;
1320   SilcServer server = (SilcServer)config->server;
1321
1322   SILC_LOG_DEBUG(("Registering configured hash functions"));
1323
1324   alg = config->hash_func;
1325   while(alg) {
1326
1327     if (!alg->sim_name) {
1328       /* Hash module is supposed to be built in. Nothing to be done
1329          here except to test that the hash function really is built in. */
1330       SilcHash tmp = NULL;
1331
1332       if (silc_hash_alloc(alg->alg_name, &tmp) == FALSE) {
1333         SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->alg_name));
1334         silc_server_stop(server);
1335         exit(1);
1336       }
1337       silc_hash_free(tmp);
1338
1339 #ifdef SILC_SIM
1340     } else {
1341       /* Load (try at least) the hash SIM module */
1342       SilcHashObject hash;
1343       SilcSimContext *sim;
1344
1345       memset(&hash, 0, sizeof(hash));
1346       hash.name = alg->alg_name;
1347       hash.block_len = alg->block_len;
1348       hash.hash_len = alg->key_len;
1349
1350       sim = silc_sim_alloc();
1351       sim->type = SILC_SIM_HASH;
1352       sim->libname = alg->sim_name;
1353
1354       if ((silc_sim_load(sim))) {
1355         hash.init = 
1356           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name, 
1357                                                 SILC_HASH_SIM_INIT));
1358         SILC_LOG_DEBUG(("init=%p", hash.init));
1359         hash.update = 
1360           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1361                                                 SILC_HASH_SIM_UPDATE));
1362         SILC_LOG_DEBUG(("update=%p", hash.update));
1363         hash.final = 
1364           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1365                                                 SILC_HASH_SIM_FINAL));
1366         SILC_LOG_DEBUG(("final=%p", hash.final));
1367         hash.context_len = 
1368           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1369                                                 SILC_HASH_SIM_CONTEXT_LEN));
1370         SILC_LOG_DEBUG(("context_len=%p", hash.context_len));
1371
1372         /* Put the SIM to the table of all SIM's in server */
1373         silc_dlist_add(server->sim, sim);
1374       } else {
1375         SILC_LOG_ERROR(("Error configuring hash functions"));
1376         silc_server_stop(server);
1377         exit(1);
1378       }
1379
1380       /* Register the hash function */
1381       silc_hash_register(&hash);
1382 #endif
1383     }
1384
1385     alg = alg->next;
1386   }
1387 }
1388
1389 /* Registers configure HMACs. These can then be allocated by the server
1390    when needed. */
1391
1392 void silc_server_config_register_hmacs(SilcServerConfig config)
1393 {
1394   SilcServerConfigSectionAlg *alg;
1395   SilcServer server = (SilcServer)config->server;
1396
1397   SILC_LOG_DEBUG(("Registering configured HMACs"));
1398
1399   if (!config->hmac) {
1400     SILC_LOG_ERROR(("HMACs are not configured. SILC cannot work without "
1401                     "HMACs"));
1402     silc_server_stop(server);
1403     exit(1);
1404   }
1405
1406   alg = config->hmac;
1407   while(alg) {
1408     SilcHmacObject hmac;
1409     
1410     if (!silc_hash_is_supported(alg->sim_name)) {
1411       SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->sim_name));
1412       silc_server_stop(server);
1413       exit(1);
1414     }
1415     
1416     /* Register the HMAC */
1417     memset(&hmac, 0, sizeof(hmac));
1418     hmac.name = alg->alg_name;
1419     hmac.len = alg->key_len;
1420     silc_hmac_register(&hmac);
1421
1422     alg = alg->next;
1423   }
1424 }
1425
1426 /* Returns client authentication information from server configuration
1427    by host (name or ip). If `port' is non-null then both name or IP and 
1428    the port must match. */
1429
1430 SilcServerConfigSectionClientConnection *
1431 silc_server_config_find_client_conn(SilcServerConfig config, 
1432                                     char *host, int port)
1433 {
1434   int i;
1435   SilcServerConfigSectionClientConnection *client = NULL;
1436   bool match = FALSE;
1437
1438   if (!host)
1439     return NULL;
1440
1441   if (!config->clients)
1442     return NULL;
1443
1444   client = config->clients;
1445
1446   for (i = 0; client; i++) {
1447     if (silc_string_compare(client->host, host))
1448       match = TRUE;
1449
1450     if (port && client->port != port)
1451       match = FALSE;
1452
1453     if (match)
1454       break;
1455
1456     client = client->next;
1457   }
1458
1459   if (!client)
1460     return NULL;
1461
1462   return client;
1463 }
1464
1465 /* Returns server connection info from server configuartion by host 
1466    (name or ip). If `port' is non-null then both name or IP and the port
1467    must match. */
1468
1469 SilcServerConfigSectionServerConnection *
1470 silc_server_config_find_server_conn(SilcServerConfig config, 
1471                                     char *host, int port)
1472 {
1473   int i;
1474   SilcServerConfigSectionServerConnection *serv = NULL;
1475   bool match = FALSE;
1476
1477   if (!host)
1478     return NULL;
1479
1480   if (!config->servers)
1481     return NULL;
1482
1483   serv = config->servers;
1484   for (i = 0; serv; i++) {
1485     if (silc_string_compare(serv->host, host))
1486       match = TRUE;
1487
1488     if (port && serv->port != port)
1489       match = FALSE;
1490
1491     if (match)
1492       break;
1493
1494     serv = serv->next;
1495   }
1496
1497   if (!serv)
1498     return NULL;
1499
1500   return serv;
1501 }
1502
1503 /* Returns router connection info from server configuartion by
1504    host (name or ip). */
1505
1506 SilcServerConfigSectionServerConnection *
1507 silc_server_config_find_router_conn(SilcServerConfig config, 
1508                                     char *host, int port)
1509 {
1510   int i;
1511   SilcServerConfigSectionServerConnection *serv = NULL;
1512   bool match = FALSE;
1513
1514   if (!host)
1515     return NULL;
1516
1517   if (!config->routers)
1518     return NULL;
1519
1520   serv = config->routers;
1521   for (i = 0; serv; i++) {
1522     if (silc_string_compare(serv->host, host))
1523       match = TRUE;
1524
1525     if (port && serv->port != port)
1526       match = FALSE;
1527
1528     if (match)
1529       break;
1530
1531     serv = serv->next;
1532   }
1533
1534   if (!serv)
1535     return NULL;
1536
1537   return serv;
1538 }
1539
1540 /* Returns TRUE if configuartion for a router connection that we are 
1541    initiating exists. */
1542
1543 bool silc_server_config_is_primary_route(SilcServerConfig config)
1544 {
1545   int i;
1546   SilcServerConfigSectionServerConnection *serv = NULL;
1547   bool found = FALSE;
1548
1549   serv = config->routers;
1550   for (i = 0; serv; i++) {
1551     if (serv->initiator == TRUE) {
1552       found = TRUE;
1553       break;
1554     }
1555
1556     serv = serv->next;
1557   }
1558
1559   return found;
1560 }
1561
1562 /* Returns Admin connection configuration by host, username and/or 
1563    nickname. */
1564
1565 SilcServerConfigSectionAdminConnection *
1566 silc_server_config_find_admin(SilcServerConfig config,
1567                               char *host, char *username, char *nickname)
1568 {
1569   SilcServerConfigSectionAdminConnection *admin = NULL;
1570   int i;
1571
1572   if (!config->admins)
1573     return NULL;
1574
1575   if (!host)
1576     host = "*";
1577   if (!username)
1578     username = "*";
1579   if (!nickname)
1580     nickname = "*";
1581
1582   admin = config->admins;
1583   for (i = 0; admin; i++) {
1584     if (silc_string_compare(admin->host, host) &&
1585         silc_string_compare(admin->username, username) &&
1586         silc_string_compare(admin->nickname, nickname))
1587       break;
1588
1589     admin = admin->next;
1590   }
1591
1592   if (!admin)
1593     return NULL;
1594
1595   return admin;
1596 }