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