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