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