Debug printing change.
[silc.git] / apps / silcd / serverconfig.c
1 /*
2
3   serverconfig.c
4
5   Author: Johnny Mnemonic <johnny@themnemonic.org>
6
7   Copyright (C) 1997 - 2002 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 #include <dirent.h>
25
26 #if 0
27 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
28 #else
29 #define SERVER_CONFIG_DEBUG(fmt)
30 #endif
31
32 /* auto-declare needed variables for the common list parsing */
33 #define SILC_SERVER_CONFIG_SECTION_INIT(__type__)                       \
34   SilcServerConfig config = (SilcServerConfig) context;                 \
35   __type__ *findtmp, *tmp = (__type__ *) config->tmp;                   \
36   int got_errno = 0
37
38 /* allocate the tmp field for fetching data */
39 #define SILC_SERVER_CONFIG_ALLOCTMP(__type__)                           \
40   if (!tmp) {                                                           \
41     config->tmp = silc_calloc(1, sizeof(*findtmp));                     \
42     tmp = (__type__ *) config->tmp;                                     \
43   }
44
45 /* append the tmp field to the specified list */
46 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__)                     \
47   if (!__list__) {                                                      \
48     __list__ = tmp;                                                     \
49   } else {                                                              \
50     for (findtmp = __list__; findtmp->next; findtmp = findtmp->next);   \
51     findtmp->next = tmp;                                                \
52   }
53
54 /* loops all elements in a list and provides a di struct pointer of the
55  * specified type containing the current element */
56 #define SILC_SERVER_CONFIG_LIST_DESTROY(__type__, __list__)             \
57   for (tmp = (void *) __list__; tmp;) {                                 \
58     __type__ *di = (__type__ *) tmp;                                    \
59     tmp = (void *) di->next;
60
61 /* Set EDOUBLE error value and bail out if necessary */
62 #define CONFIG_IS_DOUBLE(__x__)                                         \
63   if ((__x__)) {                                                        \
64     got_errno = SILC_CONFIG_EDOUBLE;                                    \
65     goto got_err;                                                       \
66   }
67
68 /* Free the authentication fields in the specified struct
69  * Expands to two instructions */
70 #define CONFIG_FREE_AUTH(__section__)                   \
71   silc_free(__section__->passphrase);                   \
72   if (__section__->publickeys)                          \
73     silc_hash_table_free(__section__->publickeys);
74
75 static void my_free_public_key(void *key, void *context, void *user_data)
76 {
77   silc_pkcs_public_key_free(context);
78 }
79
80 /* Set default values to those parameters that have not been defined */
81 static void
82 my_set_param_defaults(SilcServerConfigConnParams *params,
83                       SilcServerConfigConnParams *defaults)
84 {
85 #define SET_PARAM_DEFAULT(p, d) params->p =                             \
86   (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
87
88   SET_PARAM_DEFAULT(connections_max, SILC_SERVER_MAX_CONNECTIONS);
89   SET_PARAM_DEFAULT(connections_max_per_host,
90                     SILC_SERVER_MAX_CONNECTIONS_SINGLE);
91   SET_PARAM_DEFAULT(keepalive_secs, SILC_SERVER_KEEPALIVE);
92   SET_PARAM_DEFAULT(reconnect_count, SILC_SERVER_RETRY_COUNT);
93   SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
94   SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
95   SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
96   SET_PARAM_DEFAULT(qos_rate_limit, SILC_SERVER_QOS_RATE_LIMIT);
97   SET_PARAM_DEFAULT(qos_bytes_limit, SILC_SERVER_QOS_BYTES_LIMIT);
98   SET_PARAM_DEFAULT(qos_limit_sec, SILC_SERVER_QOS_LIMIT_SEC);
99   SET_PARAM_DEFAULT(qos_limit_usec, SILC_SERVER_QOS_LIMIT_USEC);
100
101 #undef SET_PARAM_DEFAULT
102 }
103
104 /* Find connection parameters by the parameter block name. */
105 static SilcServerConfigConnParams *
106 my_find_param(SilcServerConfig config, const char *name)
107 {
108   SilcServerConfigConnParams *param;
109
110   for (param = config->conn_params; param; param = param->next) {
111     if (!strcasecmp(param->name, name))
112       return param;
113   }
114
115   SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
116                          "Cannot find Params \"%s\".", name));
117
118   return NULL;
119 }
120
121 /* parse an authdata according to its auth method */
122 static bool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
123                               void **auth_data, SilcUInt32 *auth_data_len)
124 {
125   if (auth_meth == SILC_AUTH_PASSWORD) {
126     /* p is a plain text password */
127     if (auth_data && auth_data_len) {
128       if (!silc_utf8_valid(p, strlen(p))) {
129         *auth_data_len = silc_utf8_encoded_len(p, strlen(p),
130                                                SILC_STRING_LANGUAGE);
131         *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
132         silc_utf8_encode(p, strlen(p), SILC_STRING_LANGUAGE, *auth_data,
133                          *auth_data_len);
134       } else {
135         *auth_data = (void *) strdup(p);
136         *auth_data_len = (SilcUInt32) strlen(p);
137       }
138     }
139   } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
140     /* p is a public key file name */
141     SilcPublicKey public_key;
142     SilcPublicKey cached_key;
143
144     if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
145       if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
146         SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
147                                "Could not load public key file!"));
148         return FALSE;
149       }
150
151     if (*auth_data &&
152         silc_hash_table_find_ext(*auth_data, public_key, (void **)&cached_key,
153                                  NULL, silc_hash_public_key, NULL,
154                                  silc_hash_public_key_compare, NULL)) {
155       silc_pkcs_public_key_free(public_key);
156       SILC_SERVER_LOG_WARNING(("Warning: public key file \"%s\" already "
157                                "configured, ignoring this key", p));
158       return TRUE; /* non fatal error */
159     }
160
161     /* The auth_data is a pointer to the hash table of public keys. */
162     if (auth_data) {
163       if (*auth_data == NULL)
164         *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
165                                            NULL, NULL,
166                                            my_free_public_key, NULL,
167                                            TRUE);
168       silc_hash_table_add(*auth_data, public_key, public_key);
169     }
170   } else
171     abort();
172
173   return TRUE;
174 }
175
176 static bool my_parse_publickeydir(const char *dirname, void **auth_data)
177 {
178   int total = 0;
179   struct dirent *get_file;
180   DIR *dp;
181
182   if (!(dp = opendir(dirname))) {
183     SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
184                            "Could not open directory \"%s\"", dirname));
185     return FALSE;
186   }
187
188   /* errors are not considered fatal */
189   while ((get_file = readdir(dp))) {
190     int dirname_len = strlen(dirname);
191     char buf[1023];
192     const char *filename = get_file->d_name;
193     struct stat check_file;
194
195     if (!strcmp(filename, ".") || !strcmp(filename, ".."))
196       continue;
197
198     snprintf(buf, sizeof(buf) - 2, "%s%s%s", dirname,
199              (dirname[dirname_len - 1] == '/' ? "" : "/"), filename);
200     buf[sizeof(buf) - 1] = 0;
201
202     if (stat(buf, &check_file) < 0) {
203       SILC_SERVER_LOG_ERROR(("Error stating file %s: %s", buf,
204                              strerror(errno)));
205     }
206     else if (S_ISREG(check_file.st_mode)) {
207       my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL);
208       total++;
209     }
210   }
211
212   SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname));
213   return TRUE;
214 }
215
216 /* Callbacks */
217
218 SILC_CONFIG_CALLBACK(fetch_generic)
219 {
220   SilcServerConfig config = (SilcServerConfig) context;
221   int got_errno = 0;
222
223   if (!strcmp(name, "module_path")) {
224     CONFIG_IS_DOUBLE(config->module_path);
225     config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
226   }
227   else if (!strcmp(name, "prefer_passphrase_auth")) {
228     config->prefer_passphrase_auth = *(bool *)val;
229   }
230   else if (!strcmp(name, "require_reverse_lookup")) {
231     config->require_reverse_lookup = *(bool *)val;
232   }
233   else if (!strcmp(name, "connections_max")) {
234     config->param.connections_max = (SilcUInt32) *(int *)val;
235   }
236   else if (!strcmp(name, "connections_max_per_host")) {
237     config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
238   }
239   else if (!strcmp(name, "keepalive_secs")) {
240     config->param.keepalive_secs = (SilcUInt32) *(int *)val;
241   }
242   else if (!strcmp(name, "reconnect_count")) {
243     config->param.reconnect_count = (SilcUInt32) *(int *)val;
244   }
245   else if (!strcmp(name, "reconnect_interval")) {
246     config->param.reconnect_interval = (SilcUInt32) *(int *)val;
247   }
248   else if (!strcmp(name, "reconnect_interval_max")) {
249     config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
250   }
251   else if (!strcmp(name, "reconnect_keep_trying")) {
252     config->param.reconnect_keep_trying = *(bool *)val;
253   }
254   else if (!strcmp(name, "key_exchange_rekey")) {
255     config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
256   }
257   else if (!strcmp(name, "key_exchange_pfs")) {
258     config->param.key_exchange_pfs = *(bool *)val;
259   }
260   else if (!strcmp(name, "channel_rekey_secs")) {
261     config->channel_rekey_secs = (SilcUInt32) *(int *)val;
262   }
263   else if (!strcmp(name, "key_exchange_timeout")) {
264     config->key_exchange_timeout = (SilcUInt32) *(int *)val;
265   }
266   else if (!strcmp(name, "conn_auth_timeout")) {
267     config->conn_auth_timeout = (SilcUInt32) *(int *)val;
268   }
269   else if (!strcmp(name, "version_protocol")) {
270     CONFIG_IS_DOUBLE(config->param.version_protocol);
271     config->param.version_protocol =
272       (*(char *)val ? strdup((char *) val) : NULL);
273   }
274   else if (!strcmp(name, "version_software")) {
275     CONFIG_IS_DOUBLE(config->param.version_software);
276     config->param.version_software =
277       (*(char *)val ? strdup((char *) val) : NULL);
278   }
279   else if (!strcmp(name, "version_software_vendor")) {
280     CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
281     config->param.version_software_vendor =
282       (*(char *)val ? strdup((char *) val) : NULL);
283   }
284   else if (!strcmp(name, "detach_disabled")) {
285     config->detach_disabled = *(bool *)val;
286   }
287   else if (!strcmp(name, "detach_timeout")) {
288     config->detach_timeout = (SilcUInt32) *(int *)val;
289   }
290   else if (!strcmp(name, "qos")) {
291     config->param.qos = *(bool *)val;
292   }
293   else if (!strcmp(name, "qos_rate_limit")) {
294     config->param.qos_rate_limit = *(SilcUInt32 *)val;
295   }
296   else if (!strcmp(name, "qos_bytes_limit")) {
297     config->param.qos_bytes_limit = *(SilcUInt32 *)val;
298   }
299   else if (!strcmp(name, "qos_limit_sec")) {
300     config->param.qos_limit_sec = *(SilcUInt32 *)val;
301   }
302   else if (!strcmp(name, "qos_limit_usec")) {
303     config->param.qos_limit_usec = *(SilcUInt32 *)val;
304   }
305   else
306     return SILC_CONFIG_EINTERNAL;
307
308   return SILC_CONFIG_OK;
309
310  got_err:
311   return got_errno;
312 }
313
314 SILC_CONFIG_CALLBACK(fetch_cipher)
315 {
316   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
317
318   SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
319                        type, name, context));
320   if (type == SILC_CONFIG_ARG_BLOCK) {
321     /* check the temporary struct's fields */
322     if (!tmp) /* discard empty sub-blocks */
323       return SILC_CONFIG_OK;
324     if (!tmp->name) {
325       got_errno = SILC_CONFIG_EMISSFIELDS;
326       goto got_err;
327     }
328
329     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
330     config->tmp = NULL;
331     return SILC_CONFIG_OK;
332   }
333   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
334
335   /* Identify and save this value */
336   if (!strcmp(name, "name")) {
337     CONFIG_IS_DOUBLE(tmp->name);
338     tmp->name = strdup((char *) val);
339   }
340   else if (!strcmp(name, "module")) {
341     CONFIG_IS_DOUBLE(tmp->module);
342     tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
343   }
344   else if (!strcmp(name, "keylength")) {
345     tmp->key_length = *(SilcUInt32 *)val;
346   }
347   else if (!strcmp(name, "blocklength")) {
348     tmp->block_length = *(SilcUInt32 *)val;
349   }
350   else
351     return SILC_CONFIG_EINTERNAL;
352   return SILC_CONFIG_OK;
353
354  got_err:
355   silc_free(tmp->name);
356   silc_free(tmp->module);
357   silc_free(tmp);
358   config->tmp = NULL;
359   return got_errno;
360 }
361
362 SILC_CONFIG_CALLBACK(fetch_hash)
363 {
364   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
365
366   SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
367                        type, name, context));
368   if (type == SILC_CONFIG_ARG_BLOCK) {
369     /* check the temporary struct's fields */
370     if (!tmp) /* discard empty sub-blocks */
371       return SILC_CONFIG_OK;
372     if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
373       got_errno = SILC_CONFIG_EMISSFIELDS;
374       goto got_err;
375     }
376
377     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
378     config->tmp = NULL;
379     return SILC_CONFIG_OK;
380   }
381   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
382
383   /* Identify and save this value */
384   if (!strcmp(name, "name")) {
385     CONFIG_IS_DOUBLE(tmp->name);
386     tmp->name = strdup((char *) val);
387   }
388   else if (!strcmp(name, "module")) {
389     CONFIG_IS_DOUBLE(tmp->module);
390     tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
391   }
392   else if (!strcmp(name, "blocklength")) {
393     tmp->block_length = *(int *)val;
394   }
395   else if (!strcmp(name, "digestlength")) {
396     tmp->digest_length = *(int *)val;
397   }
398   else
399     return SILC_CONFIG_EINTERNAL;
400   return SILC_CONFIG_OK;
401
402  got_err:
403   silc_free(tmp->name);
404   silc_free(tmp->module);
405   silc_free(tmp);
406   config->tmp = NULL;
407   return got_errno;
408 }
409
410 SILC_CONFIG_CALLBACK(fetch_hmac)
411 {
412   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
413
414   SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
415                        type, name, context));
416   if (type == SILC_CONFIG_ARG_BLOCK) {
417     /* check the temporary struct's fields */
418     if (!tmp) /* discard empty sub-blocks */
419       return SILC_CONFIG_OK;
420     if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
421       got_errno = SILC_CONFIG_EMISSFIELDS;
422       goto got_err;
423     }
424
425     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
426     config->tmp = NULL;
427     return SILC_CONFIG_OK;
428   }
429   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
430
431   /* Identify and save this value */
432   if (!strcmp(name, "name")) {
433     CONFIG_IS_DOUBLE(tmp->name);
434     tmp->name = strdup((char *) val);
435   }
436   else if (!strcmp(name, "hash")) {
437     CONFIG_IS_DOUBLE(tmp->hash);
438     tmp->hash = strdup((char *) val);
439   }
440   else if (!strcmp(name, "maclength")) {
441     tmp->mac_length = *(int *)val;
442   }
443   else
444     return SILC_CONFIG_EINTERNAL;
445   return SILC_CONFIG_OK;
446
447  got_err:
448   silc_free(tmp->name);
449   silc_free(tmp->hash);
450   silc_free(tmp);
451   config->tmp = NULL;
452   return got_errno;
453 }
454
455 SILC_CONFIG_CALLBACK(fetch_pkcs)
456 {
457   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
458
459   SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
460                        type, name, context));
461   if (type == SILC_CONFIG_ARG_BLOCK) {
462     /* check the temporary struct's fields */
463     if (!tmp) /* discard empty sub-blocks */
464       return SILC_CONFIG_OK;
465     if (!tmp->name) {
466       got_errno = SILC_CONFIG_EMISSFIELDS;
467       goto got_err;
468     }
469
470     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
471     config->tmp = NULL;
472     return SILC_CONFIG_OK;
473   }
474   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
475
476   /* Identify and save this value */
477   if (!strcmp(name, "name")) {
478     CONFIG_IS_DOUBLE(tmp->name);
479     tmp->name = strdup((char *) val);
480   }
481   else
482     return SILC_CONFIG_EINTERNAL;
483   return SILC_CONFIG_OK;
484
485  got_err:
486   silc_free(tmp->name);
487   silc_free(tmp);
488   config->tmp = NULL;
489   return got_errno;
490 }
491
492 SILC_CONFIG_CALLBACK(fetch_serverinfo)
493 {
494   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
495   SilcServerConfigServerInfo *server_info = config->server_info;
496
497   /* if there isn't the struct alloc it */
498   if (!server_info)
499     config->server_info = server_info = (SilcServerConfigServerInfo *)
500                 silc_calloc(1, sizeof(*server_info));
501
502   if (type == SILC_CONFIG_ARG_BLOCK) {
503     if (!strcmp(name, "primary")) {
504       CONFIG_IS_DOUBLE(server_info->primary);
505       if (!tmp)
506         return SILC_CONFIG_OK;
507       server_info->primary = tmp;
508       config->tmp = NULL;
509       return SILC_CONFIG_OK;
510     } else if (!strcmp(name, "secondary")) {
511       if (!tmp)
512         return SILC_CONFIG_OK;
513       SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
514       config->tmp = NULL;
515       return SILC_CONFIG_OK;
516     } else if (!server_info->public_key || !server_info->private_key) {
517       got_errno = SILC_CONFIG_EMISSFIELDS;
518       goto got_err;
519     }
520     return SILC_CONFIG_OK;
521   }
522   if (!strcmp(name, "hostname")) {
523     CONFIG_IS_DOUBLE(server_info->server_name);
524     server_info->server_name = strdup((char *) val);
525   }
526   else if (!strcmp(name, "ip")) {
527     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
528     CONFIG_IS_DOUBLE(tmp->server_ip);
529     tmp->server_ip = strdup((char *) val);
530   }
531   else if (!strcmp(name, "port")) {
532     int port = *(int *)val;
533     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
534     if ((port <= 0) || (port > 65535)) {
535       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
536                              "Invalid port number!"));
537       got_errno = SILC_CONFIG_EPRINTLINE;
538       goto got_err;
539     }
540     tmp->port = (SilcUInt16) port;
541   }
542   else if (!strcmp(name, "servertype")) {
543     CONFIG_IS_DOUBLE(server_info->server_type);
544     server_info->server_type = strdup((char *) val);
545   }
546   else if (!strcmp(name, "admin")) {
547     CONFIG_IS_DOUBLE(server_info->admin);
548     server_info->admin = strdup((char *) val);
549   }
550   else if (!strcmp(name, "adminemail")) {
551     CONFIG_IS_DOUBLE(server_info->email);
552     server_info->email = strdup((char *) val);
553   }
554   else if (!strcmp(name, "location")) {
555     CONFIG_IS_DOUBLE(server_info->location);
556     server_info->location = strdup((char *) val);
557   }
558   else if (!strcmp(name, "user")) {
559     CONFIG_IS_DOUBLE(server_info->user);
560     server_info->user = strdup((char *) val);
561   }
562   else if (!strcmp(name, "group")) {
563     CONFIG_IS_DOUBLE(server_info->group);
564     server_info->group = strdup((char *) val);
565   }
566   else if (!strcmp(name, "motdfile")) {
567     CONFIG_IS_DOUBLE(server_info->motd_file);
568     server_info->motd_file = strdup((char *) val);
569   }
570   else if (!strcmp(name, "pidfile")) {
571     CONFIG_IS_DOUBLE(server_info->pid_file);
572     server_info->pid_file = strdup((char *) val);
573   }
574   else if (!strcmp(name, "publickey")) {
575     char *file_tmp = (char *) val;
576     CONFIG_IS_DOUBLE(server_info->public_key);
577
578     /* try to load specified file, if fail stop config parsing */
579     if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
580                                    SILC_PKCS_FILE_PEM))
581       if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
582                                      SILC_PKCS_FILE_BIN)) {
583         SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
584         return SILC_CONFIG_EPRINTLINE;
585       }
586   }
587   else if (!strcmp(name, "privatekey")) {
588     char *file_tmp = (char *) val;
589     CONFIG_IS_DOUBLE(server_info->private_key);
590
591     /* try to load specified file, if fail stop config parsing */
592     if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
593                                     "", 0, SILC_PKCS_FILE_BIN))
594       if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
595                                       "", 0, SILC_PKCS_FILE_PEM)) {
596         SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
597         return SILC_CONFIG_EPRINTLINE;
598       }
599   }
600   else
601     return SILC_CONFIG_EINTERNAL;
602   return SILC_CONFIG_OK;
603
604  got_err:
605   silc_free(tmp);
606   silc_free(config->tmp);
607   config->tmp = NULL;
608   return got_errno;
609 }
610
611 SILC_CONFIG_CALLBACK(fetch_logging)
612 {
613   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
614
615   if (!strcmp(name, "timestamp")) {
616     config->logging_timestamp = *(bool *)val;
617   }
618   else if (!strcmp(name, "quicklogs")) {
619     config->logging_quick = *(bool *)val;
620   }
621   else if (!strcmp(name, "flushdelay")) {
622     int flushdelay = *(int *)val;
623     if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
624       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
625                             "Invalid flushdelay value, use quicklogs if you "
626                             "want real-time logging."));
627       return SILC_CONFIG_EPRINTLINE;
628     }
629     config->logging_flushdelay = (long) flushdelay;
630   }
631
632   /* The following istances happens only in Logging's sub-blocks, a match
633      for the sub-block name means that you should store the filename/maxsize
634      temporary struct to the proper logging channel.
635      If we get a match for "file" or "maxsize" this means that we are inside
636      a sub-sub-block and it is safe to alloc a new tmp. */
637 #define FETCH_LOGGING_CHAN(__chan__, __member__)                \
638   else if (!strcmp(name, __chan__)) {                           \
639     if (!tmp) return SILC_CONFIG_OK;                            \
640     if (!tmp->file) {                                           \
641       got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err;        \
642     }                                                           \
643     config->__member__ = tmp;                                   \
644     config->tmp = NULL;                                         \
645   }
646   FETCH_LOGGING_CHAN("info", logging_info)
647   FETCH_LOGGING_CHAN("warnings", logging_warnings)
648   FETCH_LOGGING_CHAN("errors", logging_errors)
649   FETCH_LOGGING_CHAN("fatals", logging_fatals)
650 #undef FETCH_LOGGING_CHAN
651   else if (!strcmp(name, "file")) {
652     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
653     CONFIG_IS_DOUBLE(tmp->file);
654     tmp->file = strdup((char *) val);
655   }
656   else if (!strcmp(name, "size")) {
657     if (!tmp) {
658       config->tmp = silc_calloc(1, sizeof(*tmp));
659       tmp = (SilcServerConfigLogging *) config->tmp;
660     }
661     tmp->maxsize = *(SilcUInt32 *) val;
662   }
663   else
664     return SILC_CONFIG_EINTERNAL;
665   return SILC_CONFIG_OK;
666
667  got_err:
668   silc_free(tmp->file);
669   silc_free(tmp);
670   config->tmp = NULL;
671   return got_errno;
672 }
673
674 SILC_CONFIG_CALLBACK(fetch_connparam)
675 {
676   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
677
678   SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
679                        type, name, context));
680   if (type == SILC_CONFIG_ARG_BLOCK) {
681     /* check the temporary struct's fields */
682     if (!tmp) /* discard empty sub-blocks */
683       return SILC_CONFIG_OK;
684     if (!tmp->name) {
685       got_errno = SILC_CONFIG_EMISSFIELDS;
686       goto got_err;
687     }
688     /* Set defaults */
689     my_set_param_defaults(tmp, &config->param);
690
691     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
692     config->tmp = NULL;
693     return SILC_CONFIG_OK;
694   }
695   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
696
697   if (!strcmp(name, "name")) {
698     CONFIG_IS_DOUBLE(tmp->name);
699     tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
700   }
701   else if (!strcmp(name, "connections_max")) {
702     tmp->connections_max = *(SilcUInt32 *)val;
703   }
704   else if (!strcmp(name, "connections_max_per_host")) {
705     tmp->connections_max_per_host = *(SilcUInt32 *)val;
706   }
707   else if (!strcmp(name, "keepalive_secs")) {
708     tmp->keepalive_secs = *(SilcUInt32 *)val;
709   }
710   else if (!strcmp(name, "reconnect_count")) {
711     tmp->reconnect_count = *(SilcUInt32 *)val;
712   }
713   else if (!strcmp(name, "reconnect_interval")) {
714     tmp->reconnect_interval = *(SilcUInt32 *)val;
715   }
716   else if (!strcmp(name, "reconnect_interval_max")) {
717     tmp->reconnect_interval_max = *(SilcUInt32 *)val;
718   }
719   else if (!strcmp(name, "reconnect_keep_trying")) {
720     tmp->reconnect_keep_trying = *(bool *)val;
721   }
722   else if (!strcmp(name, "key_exchange_rekey")) {
723     tmp->key_exchange_rekey = *(SilcUInt32 *)val;
724   }
725   else if (!strcmp(name, "key_exchange_pfs")) {
726     tmp->key_exchange_pfs = *(bool *)val;
727   }
728   else if (!strcmp(name, "version_protocol")) {
729     CONFIG_IS_DOUBLE(tmp->version_protocol);
730     tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
731   }
732   else if (!strcmp(name, "version_software")) {
733     CONFIG_IS_DOUBLE(tmp->version_software);
734     tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
735   }
736   else if (!strcmp(name, "version_software_vendor")) {
737     CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
738     tmp->version_software_vendor =
739       (*(char *)val ? strdup((char *) val) : NULL);
740   }
741   else if (!strcmp(name, "anonymous")) {
742     tmp->anonymous = *(bool *)val;
743   }
744   else if (!strcmp(name, "qos")) {
745     tmp->qos = *(bool *)val;
746   }
747   else if (!strcmp(name, "qos_rate_limit")) {
748     tmp->qos_rate_limit = *(SilcUInt32 *)val;
749   }
750   else if (!strcmp(name, "qos_bytes_limit")) {
751     tmp->qos_bytes_limit = *(SilcUInt32 *)val;
752   }
753   else if (!strcmp(name, "qos_limit_sec")) {
754     tmp->qos_limit_sec = *(SilcUInt32 *)val;
755   }
756   else if (!strcmp(name, "qos_limit_usec")) {
757     tmp->qos_limit_usec = *(SilcUInt32 *)val;
758   }
759   else
760     return SILC_CONFIG_EINTERNAL;
761
762   return SILC_CONFIG_OK;
763
764  got_err:
765   silc_free(tmp->name);
766   silc_free(tmp);
767   config->tmp = NULL;
768   return got_errno;
769 }
770
771 SILC_CONFIG_CALLBACK(fetch_client)
772 {
773   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
774
775   SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
776                        type, name, context));
777
778   /* Alloc before block checking, because empty sub-blocks are welcome here */
779   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
780
781   if (type == SILC_CONFIG_ARG_BLOCK) {
782     /* empty sub-blocks are welcome */
783     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
784     config->tmp = NULL;
785     return SILC_CONFIG_OK;
786   }
787
788   /* Identify and save this value */
789   if (!strcmp(name, "host")) {
790     CONFIG_IS_DOUBLE(tmp->host);
791     tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
792   }
793   else if (!strcmp(name, "passphrase")) {
794     CONFIG_IS_DOUBLE(tmp->passphrase);
795     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
796                            (void **)&tmp->passphrase,
797                            &tmp->passphrase_len)) {
798       got_errno = SILC_CONFIG_EPRINTLINE;
799       goto got_err;
800     }
801   }
802   else if (!strcmp(name, "publickey")) {
803     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
804                            (void **)&tmp->publickeys, NULL)) {
805       got_errno = SILC_CONFIG_EPRINTLINE;
806       goto got_err;
807     }
808   }
809   else if (!strcmp(name, "publickeydir")) {
810     if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) {
811       got_errno = SILC_CONFIG_EPRINTLINE;
812       goto got_err;
813     }
814   }
815   else if (!strcmp(name, "params")) {
816     CONFIG_IS_DOUBLE(tmp->param);
817     tmp->param = my_find_param(config, (char *) val);
818     if (!tmp->param) { /* error message already output */
819       got_errno = SILC_CONFIG_EPRINTLINE;
820       goto got_err;
821     }
822   }
823   else
824     return SILC_CONFIG_EINTERNAL;
825   return SILC_CONFIG_OK;
826
827  got_err:
828   silc_free(tmp->host);
829   CONFIG_FREE_AUTH(tmp);
830   silc_free(tmp);
831   config->tmp = NULL;
832   return got_errno;
833 }
834
835 SILC_CONFIG_CALLBACK(fetch_admin)
836 {
837   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
838
839   SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
840                        type, name, context));
841   if (type == SILC_CONFIG_ARG_BLOCK) {
842     /* check the temporary struct's fields */
843     if (!tmp) /* discard empty sub-blocks */
844       return SILC_CONFIG_OK;
845
846     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
847     config->tmp = NULL;
848     return SILC_CONFIG_OK;
849   }
850   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
851
852   /* Identify and save this value */
853   if (!strcmp(name, "host")) {
854     CONFIG_IS_DOUBLE(tmp->host);
855     tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
856   }
857   else if (!strcmp(name, "user")) {
858     CONFIG_IS_DOUBLE(tmp->user);
859     tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
860   }
861   else if (!strcmp(name, "nick")) {
862     CONFIG_IS_DOUBLE(tmp->nick);
863     tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
864   }
865   else if (!strcmp(name, "passphrase")) {
866     CONFIG_IS_DOUBLE(tmp->passphrase);
867     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
868                            (void **)&tmp->passphrase,
869                            &tmp->passphrase_len)) {
870       got_errno = SILC_CONFIG_EPRINTLINE;
871       goto got_err;
872     }
873   }
874   else if (!strcmp(name, "publickey")) {
875     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
876                            (void **)&tmp->publickeys, NULL)) {
877       got_errno = SILC_CONFIG_EPRINTLINE;
878       goto got_err;
879     }
880   }
881   else if (!strcmp(name, "publickeydir")) {
882     if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) {
883       got_errno = SILC_CONFIG_EPRINTLINE;
884       goto got_err;
885     }
886   }
887   else
888     return SILC_CONFIG_EINTERNAL;
889   return SILC_CONFIG_OK;
890
891  got_err:
892   silc_free(tmp->host);
893   silc_free(tmp->user);
894   silc_free(tmp->nick);
895   CONFIG_FREE_AUTH(tmp);
896   silc_free(tmp);
897   config->tmp = NULL;
898   return got_errno;
899 }
900
901 SILC_CONFIG_CALLBACK(fetch_deny)
902 {
903   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
904
905   SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
906                        type, name, context));
907   if (type == SILC_CONFIG_ARG_BLOCK) {
908     /* check the temporary struct's fields */
909     if (!tmp) /* discard empty sub-blocks */
910       return SILC_CONFIG_OK;
911     if (!tmp->reason) {
912       got_errno = SILC_CONFIG_EMISSFIELDS;
913       goto got_err;
914     }
915
916     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
917     config->tmp = NULL;
918     return SILC_CONFIG_OK;
919   }
920   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
921
922   /* Identify and save this value */
923   if (!strcmp(name, "host")) {
924     CONFIG_IS_DOUBLE(tmp->host);
925     tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
926   }
927   else if (!strcmp(name, "reason")) {
928     CONFIG_IS_DOUBLE(tmp->reason);
929     tmp->reason = strdup((char *) val);
930   }
931   else
932     return SILC_CONFIG_EINTERNAL;
933   return SILC_CONFIG_OK;
934
935  got_err:
936   silc_free(tmp->host);
937   silc_free(tmp->reason);
938   silc_free(tmp);
939   config->tmp = NULL;
940   return got_errno;
941 }
942
943 SILC_CONFIG_CALLBACK(fetch_server)
944 {
945   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
946
947   SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
948                        type, name, context));
949   if (type == SILC_CONFIG_ARG_BLOCK) {
950     /* check the temporary struct's fields */
951     if (!tmp) /* discard empty sub-blocks */
952       return SILC_CONFIG_OK;
953
954     /* the temporary struct is ok, append it to the list */
955     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
956     config->tmp = NULL;
957     return SILC_CONFIG_OK;
958   }
959   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
960
961   /* Identify and save this value */
962   if (!strcmp(name, "host")) {
963     CONFIG_IS_DOUBLE(tmp->host);
964     tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
965   }
966   else if (!strcmp(name, "passphrase")) {
967     CONFIG_IS_DOUBLE(tmp->passphrase);
968     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
969                            (void **)&tmp->passphrase,
970                            &tmp->passphrase_len)) {
971       got_errno = SILC_CONFIG_EPRINTLINE;
972       goto got_err;
973     }
974   }
975   else if (!strcmp(name, "publickey")) {
976     CONFIG_IS_DOUBLE(tmp->publickeys);
977     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
978                            (void **)&tmp->publickeys, NULL)) {
979       got_errno = SILC_CONFIG_EPRINTLINE;
980       goto got_err;
981     }
982   }
983   else if (!strcmp(name, "params")) {
984     CONFIG_IS_DOUBLE(tmp->param);
985     tmp->param = my_find_param(config, (char *) val);
986     if (!tmp->param) { /* error message already output */
987       got_errno = SILC_CONFIG_EPRINTLINE;
988       goto got_err;
989     }
990   }
991   else if (!strcmp(name, "backup")) {
992     tmp->backup_router = *(bool *)val;
993   }
994   else
995     return SILC_CONFIG_EINTERNAL;
996
997   return SILC_CONFIG_OK;
998
999  got_err:
1000   silc_free(tmp->host);
1001   CONFIG_FREE_AUTH(tmp);
1002   silc_free(tmp);
1003   config->tmp = NULL;
1004   return got_errno;
1005 }
1006
1007 SILC_CONFIG_CALLBACK(fetch_router)
1008 {
1009   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
1010
1011   SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
1012                        type, name, context));
1013   if (type == SILC_CONFIG_ARG_BLOCK) {
1014     if (!tmp) /* discard empty sub-blocks */
1015       return SILC_CONFIG_OK;
1016
1017     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
1018     config->tmp = NULL;
1019     return SILC_CONFIG_OK;
1020   }
1021   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
1022
1023   /* Identify and save this value */
1024   if (!strcmp(name, "host")) {
1025     CONFIG_IS_DOUBLE(tmp->host);
1026     tmp->host = strdup((char *) val);
1027   }
1028   else if (!strcmp(name, "port")) {
1029     int port = *(int *)val;
1030     if ((port <= 0) || (port > 65535)) {
1031       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1032                              "Invalid port number!"));
1033       got_errno = SILC_CONFIG_EPRINTLINE;
1034       goto got_err;
1035     }
1036     tmp->port = (SilcUInt16) port;
1037   }
1038   else if (!strcmp(name, "passphrase")) {
1039     CONFIG_IS_DOUBLE(tmp->passphrase);
1040     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1041                            (void **)&tmp->passphrase,
1042                            &tmp->passphrase_len)) {
1043       got_errno = SILC_CONFIG_EPRINTLINE;
1044       goto got_err;
1045     }
1046   }
1047   else if (!strcmp(name, "publickey")) {
1048     CONFIG_IS_DOUBLE(tmp->publickeys);
1049     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1050                            (void **)&tmp->publickeys, NULL)) {
1051       got_errno = SILC_CONFIG_EPRINTLINE;
1052       goto got_err;
1053     }
1054   }
1055   else if (!strcmp(name, "params")) {
1056     CONFIG_IS_DOUBLE(tmp->param);
1057     tmp->param = my_find_param(config, (char *) val);
1058     if (!tmp->param) { /* error message already output */
1059       got_errno = SILC_CONFIG_EPRINTLINE;
1060       goto got_err;
1061     }
1062   }
1063   else if (!strcmp(name, "initiator")) {
1064     tmp->initiator = *(bool *)val;
1065   }
1066   else if (!strcmp(name, "backuphost")) {
1067     CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
1068     tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
1069                               strdup("*"));
1070     tmp->backup_router = TRUE;
1071   }
1072   else if (!strcmp(name, "backupport")) {
1073     int port = *(int *)val;
1074     if ((port <= 0) || (port > 65535)) {
1075       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1076                              "Invalid port number!"));
1077       got_errno = SILC_CONFIG_EPRINTLINE;
1078       goto got_err;
1079     }
1080     tmp->backup_replace_port = (SilcUInt16) port;
1081   }
1082   else if (!strcmp(name, "backuplocal")) {
1083     tmp->backup_local = *(bool *)val;
1084   }
1085   else
1086     return SILC_CONFIG_EINTERNAL;
1087
1088   return SILC_CONFIG_OK;
1089
1090  got_err:
1091   silc_free(tmp->host);
1092   silc_free(tmp->backup_replace_ip);
1093   CONFIG_FREE_AUTH(tmp);
1094   silc_free(tmp);
1095   config->tmp = NULL;
1096   return got_errno;
1097 }
1098
1099 /* known config options tables */
1100 static const SilcConfigTable table_general[] = {
1101   { "module_path",              SILC_CONFIG_ARG_STRE,   fetch_generic,  NULL },
1102   { "prefer_passphrase_auth",   SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1103   { "require_reverse_lookup",   SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1104   { "connections_max",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1105   { "connections_max_per_host", SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1106   { "keepalive_secs",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1107   { "reconnect_count",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1108   { "reconnect_interval",       SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1109   { "reconnect_interval_max",   SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1110   { "reconnect_keep_trying",    SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1111   { "key_exchange_rekey",       SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1112   { "key_exchange_pfs",         SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1113   { "channel_rekey_secs",       SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1114   { "key_exchange_timeout",     SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1115   { "conn_auth_timeout",        SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1116   { "version_protocol",         SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
1117   { "version_software",         SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
1118   { "version_software_vendor",  SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
1119   { "detach_disabled",          SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1120   { "detach_timeout",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1121   { "qos",                      SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1122   { "qos_rate_limit",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1123   { "qos_bytes_limit",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1124   { "qos_limit_sec",            SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1125   { "qos_limit_usec",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1126   { 0, 0, 0, 0 }
1127 };
1128
1129 static const SilcConfigTable table_cipher[] = {
1130   { "name",             SILC_CONFIG_ARG_STR,    fetch_cipher,   NULL },
1131   { "module",           SILC_CONFIG_ARG_STRE,   fetch_cipher,   NULL },
1132   { "keylength",        SILC_CONFIG_ARG_INT,    fetch_cipher,   NULL },
1133   { "blocklength",      SILC_CONFIG_ARG_INT,    fetch_cipher,   NULL },
1134   { 0, 0, 0, 0 }
1135 };
1136
1137 static const SilcConfigTable table_hash[] = {
1138   { "name",             SILC_CONFIG_ARG_STR,    fetch_hash,     NULL },
1139   { "module",           SILC_CONFIG_ARG_STRE,   fetch_hash,     NULL },
1140   { "blocklength",      SILC_CONFIG_ARG_INT,    fetch_hash,     NULL },
1141   { "digestlength",     SILC_CONFIG_ARG_INT,    fetch_hash,     NULL },
1142   { 0, 0, 0, 0 }
1143 };
1144
1145 static const SilcConfigTable table_hmac[] = {
1146   { "name",             SILC_CONFIG_ARG_STR,    fetch_hmac,     NULL },
1147   { "hash",             SILC_CONFIG_ARG_STR,    fetch_hmac,     NULL },
1148   { "maclength",        SILC_CONFIG_ARG_INT,    fetch_hmac,     NULL },
1149   { 0, 0, 0, 0 }
1150 };
1151
1152 static const SilcConfigTable table_pkcs[] = {
1153   { "name",             SILC_CONFIG_ARG_STR,    fetch_pkcs,     NULL },
1154   { 0, 0, 0, 0 }
1155 };
1156
1157 static const SilcConfigTable table_serverinfo_c[] = {
1158   { "ip",               SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1159   { "port",             SILC_CONFIG_ARG_INT,    fetch_serverinfo, NULL},
1160   { 0, 0, 0, 0 }
1161 };
1162
1163 static const SilcConfigTable table_serverinfo[] = {
1164   { "hostname",         SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1165   { "primary",          SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo_c},
1166   { "secondary",        SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo_c},
1167   { "servertype",       SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1168   { "location",         SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1169   { "admin",            SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1170   { "adminemail",       SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1171   { "user",             SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1172   { "group",            SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1173   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1174   { "privatekey",       SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1175   { "motdfile",         SILC_CONFIG_ARG_STRE,   fetch_serverinfo, NULL},
1176   { "pidfile",          SILC_CONFIG_ARG_STRE,   fetch_serverinfo, NULL},
1177   { 0, 0, 0, 0 }
1178 };
1179
1180 static const SilcConfigTable table_logging_c[] = {
1181   { "file",             SILC_CONFIG_ARG_STR,    fetch_logging,  NULL },
1182   { "size",             SILC_CONFIG_ARG_SIZE,   fetch_logging,  NULL },
1183 /*{ "quicklog",         SILC_CONFIG_ARG_NONE,   fetch_logging,  NULL }, */
1184   { 0, 0, 0, 0 }
1185 };
1186
1187 static const SilcConfigTable table_logging[] = {
1188   { "timestamp",        SILC_CONFIG_ARG_TOGGLE, fetch_logging,  NULL },
1189   { "quicklogs",        SILC_CONFIG_ARG_TOGGLE, fetch_logging,  NULL },
1190   { "flushdelay",       SILC_CONFIG_ARG_INT,    fetch_logging,  NULL },
1191   { "info",             SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1192   { "warnings",         SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1193   { "errors",           SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1194   { "fatals",           SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1195   { 0, 0, 0, 0 }
1196 };
1197
1198 static const SilcConfigTable table_connparam[] = {
1199   { "name",                    SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1200   { "require_reverse_lookup",  SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1201   { "connections_max",         SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1202   { "connections_max_per_host",SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1203   { "keepalive_secs",          SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1204   { "reconnect_count",         SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1205   { "reconnect_interval",      SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1206   { "reconnect_interval_max",  SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1207   { "reconnect_keep_trying",   SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1208   { "key_exchange_rekey",      SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1209   { "key_exchange_pfs",        SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1210   { "version_protocol",        SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1211   { "version_software",        SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1212   { "version_software_vendor", SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1213   { "anonymous",               SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1214   { "qos",                     SILC_CONFIG_ARG_TOGGLE,  fetch_generic,  NULL },
1215   { "qos_rate_limit",          SILC_CONFIG_ARG_INT,     fetch_generic,  NULL },
1216   { "qos_bytes_limit",         SILC_CONFIG_ARG_INT,     fetch_generic,  NULL },
1217   { "qos_limit_sec",           SILC_CONFIG_ARG_INT,     fetch_generic,  NULL },
1218   { "qos_limit_usec",          SILC_CONFIG_ARG_INT,     fetch_generic,  NULL },
1219   { 0, 0, 0, 0 }
1220 };
1221
1222 static const SilcConfigTable table_client[] = {
1223   { "host",             SILC_CONFIG_ARG_STRE,   fetch_client,   NULL },
1224   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1225   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1226   { "publickeydir",     SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1227   { "params",           SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1228   { 0, 0, 0, 0 }
1229 };
1230
1231 static const SilcConfigTable table_admin[] = {
1232   { "host",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1233   { "user",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1234   { "nick",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1235   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1236   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1237   { "publickeydir",     SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1238   { "port",             SILC_CONFIG_ARG_INT,    fetch_admin,    NULL },
1239   { "params",           SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1240   { 0, 0, 0, 0 }
1241 };
1242
1243 static const SilcConfigTable table_deny[] = {
1244   { "host",             SILC_CONFIG_ARG_STRE,   fetch_deny,     NULL },
1245   { "reason",           SILC_CONFIG_ARG_STR,    fetch_deny,     NULL },
1246   { 0, 0, 0, 0 }
1247 };
1248
1249 static const SilcConfigTable table_serverconn[] = {
1250   { "host",             SILC_CONFIG_ARG_STRE,   fetch_server,   NULL },
1251   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1252   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1253   { "params",           SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1254   { "backup",           SILC_CONFIG_ARG_TOGGLE, fetch_server,   NULL },
1255   { 0, 0, 0, 0 }
1256 };
1257
1258 static const SilcConfigTable table_routerconn[] = {
1259   { "host",             SILC_CONFIG_ARG_STRE,   fetch_router,   NULL },
1260   { "port",             SILC_CONFIG_ARG_INT,    fetch_router,   NULL },
1261   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1262   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1263   { "params",           SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1264   { "initiator",        SILC_CONFIG_ARG_TOGGLE, fetch_router,   NULL },
1265   { "backuphost",       SILC_CONFIG_ARG_STRE,   fetch_router,   NULL },
1266   { "backupport",       SILC_CONFIG_ARG_INT,    fetch_router,   NULL },
1267   { "backuplocal",      SILC_CONFIG_ARG_TOGGLE, fetch_router,   NULL },
1268   { 0, 0, 0, 0 }
1269 };
1270
1271 static const SilcConfigTable table_main[] = {
1272   { "cipher",           SILC_CONFIG_ARG_BLOCK,  fetch_cipher,  table_cipher },
1273   { "hash",             SILC_CONFIG_ARG_BLOCK,  fetch_hash,    table_hash },
1274   { "hmac",             SILC_CONFIG_ARG_BLOCK,  fetch_hmac,    table_hmac },
1275   { "pkcs",             SILC_CONFIG_ARG_BLOCK,  fetch_pkcs,    table_pkcs },
1276   { "general",          SILC_CONFIG_ARG_BLOCK,  NULL,          table_general },
1277   { "serverinfo",       SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo },
1278   { "logging",          SILC_CONFIG_ARG_BLOCK,  NULL,          table_logging },
1279   { "connectionparams", SILC_CONFIG_ARG_BLOCK,  fetch_connparam, table_connparam },
1280   { "client",           SILC_CONFIG_ARG_BLOCK,  fetch_client,  table_client },
1281   { "admin",            SILC_CONFIG_ARG_BLOCK,  fetch_admin,   table_admin },
1282   { "deny",             SILC_CONFIG_ARG_BLOCK,  fetch_deny,    table_deny },
1283   { "serverconnection", SILC_CONFIG_ARG_BLOCK,  fetch_server,  table_serverconn },
1284   { "routerconnection", SILC_CONFIG_ARG_BLOCK,  fetch_router,  table_routerconn },
1285   { 0, 0, 0, 0 }
1286 };
1287
1288 /* Set default values to stuff that was not configured. */
1289
1290 static void silc_server_config_set_defaults(SilcServerConfig config)
1291 {
1292   my_set_param_defaults(&config->param, NULL);
1293
1294   config->channel_rekey_secs = (config->channel_rekey_secs ?
1295                                 config->channel_rekey_secs :
1296                                 SILC_SERVER_CHANNEL_REKEY);
1297   config->key_exchange_timeout = (config->key_exchange_timeout ?
1298                                   config->key_exchange_timeout :
1299                                   SILC_SERVER_SKE_TIMEOUT);
1300   config->conn_auth_timeout = (config->conn_auth_timeout ?
1301                                config->conn_auth_timeout :
1302                                SILC_SERVER_CONNAUTH_TIMEOUT);
1303 }
1304
1305 /* Allocates a new configuration object, opens configuration file and
1306    parses it. The parsed data is returned to the newly allocated
1307    configuration object. The SilcServerConfig must be freed by calling
1308    the silc_server_config_destroy function. */
1309
1310 SilcServerConfig silc_server_config_alloc(const char *filename)
1311 {
1312   SilcServerConfig config_new;
1313   SilcConfigEntity ent;
1314   SilcConfigFile *file;
1315   int ret;
1316   SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1317
1318   /* alloc a config object */
1319   config_new = silc_calloc(1, sizeof(*config_new));
1320   if (!config_new)
1321     return NULL;
1322
1323   /* general config defaults */
1324   config_new->refcount = 1;
1325   config_new->logging_timestamp = TRUE;
1326
1327   /* obtain a config file object */
1328   file = silc_config_open(filename);
1329   if (!file) {
1330     SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
1331                            filename));
1332     return NULL;
1333   }
1334
1335   /* obtain a SilcConfig entity, we can use it to start the parsing */
1336   ent = silc_config_init(file);
1337
1338   /* load the known configuration options, give our empty object as context */
1339   silc_config_register_table(ent, table_main, (void *) config_new);
1340
1341   /* enter the main parsing loop.  When this returns, we have the parsing
1342    * result and the object filled (or partially, in case of errors). */
1343   ret = silc_config_main(ent);
1344   SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1345                   silc_config_strerror(ret)));
1346
1347   /* Check if the parser returned errors */
1348   if (ret) {
1349     /* handle this special error return which asks to quietly return */
1350     if (ret != SILC_CONFIG_ESILENT) {
1351       char *linebuf, *filename = silc_config_get_filename(file);
1352       SilcUInt32 line = silc_config_get_line(file);
1353       if (ret != SILC_CONFIG_EPRINTLINE)
1354         SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
1355                                silc_config_strerror(ret)));
1356       linebuf = silc_config_read_line(file, line);
1357       SILC_SERVER_LOG_ERROR(("  file %s line %lu:  %s\n", filename,
1358                              line, linebuf));
1359       silc_free(linebuf);
1360     }
1361     silc_server_config_destroy(config_new);
1362     return NULL;
1363   }
1364
1365   /* close (destroy) the file object */
1366   silc_config_close(file);
1367
1368   /* If config_new is incomplete, abort the object and return NULL */
1369   if (!config_new->server_info) {
1370     SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1371                            "`server_info'"));
1372     silc_server_config_destroy(config_new);
1373     return NULL;
1374   }
1375
1376   /* Set default to configuration parameters */
1377   silc_server_config_set_defaults(config_new);
1378
1379   return config_new;
1380 }
1381
1382 /* Increments the reference counter of a config object */
1383
1384 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1385                             void *ref_ptr)
1386 {
1387   if (ref_ptr) {
1388     config->refcount++;
1389     ref->config = config;
1390     ref->ref_ptr = ref_ptr;
1391     SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1392                     config->refcount - 1, config->refcount));
1393   }
1394 }
1395
1396 /* Decrements the reference counter of a config object.  If the counter
1397    reaches 0, the config object is destroyed. */
1398
1399 void silc_server_config_unref(SilcServerConfigRef *ref)
1400 {
1401   if (ref->ref_ptr)
1402     silc_server_config_destroy(ref->config);
1403 }
1404
1405 /* Destroy a config object with all his children lists */
1406
1407 void silc_server_config_destroy(SilcServerConfig config)
1408 {
1409   void *tmp;
1410
1411   config->refcount--;
1412   SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1413                   config->refcount + 1, config->refcount));
1414   if (config->refcount > 0)
1415     return;
1416
1417   SILC_LOG_DEBUG(("Freeing config context"));
1418
1419   /* Destroy general config stuff */
1420   silc_free(config->module_path);
1421   silc_free(config->param.version_protocol);
1422   silc_free(config->param.version_software);
1423   silc_free(config->param.version_software_vendor);
1424
1425   /* Destroy Logging channels */
1426   if (config->logging_info)
1427     silc_free(config->logging_info->file);
1428   if (config->logging_warnings)
1429     silc_free(config->logging_warnings->file);
1430   if (config->logging_errors)
1431     silc_free(config->logging_errors->file);
1432   if (config->logging_fatals)
1433     silc_free(config->logging_fatals->file);
1434   silc_free(config->logging_info);
1435   silc_free(config->logging_warnings);
1436   silc_free(config->logging_errors);
1437   silc_free(config->logging_fatals);
1438
1439   /* Destroy the ServerInfo struct */
1440   if (config->server_info) {
1441     register SilcServerConfigServerInfo *si = config->server_info;
1442     silc_free(si->server_name);
1443     if (si->primary) {
1444       silc_free(si->primary->server_ip);
1445       silc_free(si->primary);
1446     }
1447     SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1448                                   si->secondary)
1449       silc_free(di->server_ip);
1450       silc_free(di);
1451     }
1452     silc_free(si->server_type);
1453     silc_free(si->location);
1454     silc_free(si->admin);
1455     silc_free(si->email);
1456     silc_free(si->user);
1457     silc_free(si->group);
1458     silc_free(si->motd_file);
1459     silc_free(si->pid_file);
1460     silc_pkcs_public_key_free(si->public_key);
1461     silc_pkcs_private_key_free(si->private_key);
1462     silc_free(si);
1463   }
1464
1465   /* Now let's destroy the lists */
1466
1467   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1468                                   config->cipher)
1469     silc_free(di->name);
1470     silc_free(di->module);
1471     silc_free(di);
1472   }
1473   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1474     silc_free(di->name);
1475     silc_free(di->module);
1476     silc_free(di);
1477   }
1478   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1479     silc_free(di->name);
1480     silc_free(di->hash);
1481     silc_free(di);
1482   }
1483   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1484     silc_free(di->name);
1485     silc_free(di);
1486   }
1487   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1488                                   config->conn_params)
1489     silc_free(di->name);
1490     silc_free(di->version_protocol);
1491     silc_free(di->version_software);
1492     silc_free(di->version_software_vendor);
1493     silc_free(di);
1494   }
1495   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1496     silc_free(di->host);
1497     CONFIG_FREE_AUTH(di);
1498     silc_free(di);
1499   }
1500   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1501     silc_free(di->host);
1502     silc_free(di->user);
1503     silc_free(di->nick);
1504     CONFIG_FREE_AUTH(di);
1505     silc_free(di);
1506   }
1507   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1508     silc_free(di->host);
1509     silc_free(di->reason);
1510     silc_free(di);
1511   }
1512   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1513                                   config->servers)
1514     silc_free(di->host);
1515     CONFIG_FREE_AUTH(di);
1516     silc_free(di);
1517   }
1518   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1519                                   config->routers)
1520     silc_free(di->host);
1521     silc_free(di->backup_replace_ip);
1522     CONFIG_FREE_AUTH(di);
1523     silc_free(di);
1524   }
1525
1526   memset(config, 'F', sizeof(*config));
1527   silc_free(config);
1528 }
1529
1530 /* Registers configured ciphers. These can then be allocated by the
1531    server when needed. */
1532
1533 bool silc_server_config_register_ciphers(SilcServer server)
1534 {
1535   SilcServerConfig config = server->config;
1536   SilcServerConfigCipher *cipher = config->cipher;
1537   char *module_path = config->module_path;
1538
1539   SILC_LOG_DEBUG(("Registering configured ciphers"));
1540
1541   if (!cipher) /* any cipher in the config file? */
1542     return FALSE;
1543
1544   while (cipher) {
1545     /* if there isn't a module_path OR there isn't a module sim name try to
1546      * use buil-in functions */
1547     if (!module_path || !cipher->module) {
1548       int i;
1549       for (i = 0; silc_default_ciphers[i].name; i++)
1550         if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1551           silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1552           break;
1553         }
1554       if (!silc_cipher_is_supported(cipher->name)) {
1555         SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1556         silc_server_stop(server);
1557         exit(1);
1558       }
1559     } else {
1560 #ifdef SILC_SIM
1561       /* Load (try at least) the crypto SIM module */
1562       char buf[1023], *alg_name;
1563       SilcCipherObject cipher_obj;
1564       SilcSim sim;
1565
1566       memset(&cipher_obj, 0, sizeof(cipher_obj));
1567       cipher_obj.name = cipher->name;
1568       cipher_obj.block_len = cipher->block_length;
1569       cipher_obj.key_len = cipher->key_length * 8;
1570
1571       /* build the libname */
1572       snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1573                 cipher->module);
1574       sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1575
1576       alg_name = strdup(cipher->name);
1577       if (strchr(alg_name, '-'))
1578         *strchr(alg_name, '-') = '\0';
1579
1580       if (silc_sim_load(sim)) {
1581         cipher_obj.set_key =
1582           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1583                                                 SILC_CIPHER_SIM_SET_KEY));
1584         SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1585         cipher_obj.set_key_with_string =
1586           silc_sim_getsym(sim,
1587             silc_sim_symname(alg_name,
1588               SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1589         SILC_LOG_DEBUG(("set_key_with_string=%p",
1590           cipher_obj.set_key_with_string));
1591         cipher_obj.encrypt =
1592           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1593                                                 SILC_CIPHER_SIM_ENCRYPT_CBC));
1594         SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1595         cipher_obj.decrypt =
1596           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1597                                                 SILC_CIPHER_SIM_DECRYPT_CBC));
1598         SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1599         cipher_obj.context_len =
1600           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1601                                                 SILC_CIPHER_SIM_CONTEXT_LEN));
1602         SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1603
1604         /* Put the SIM to the list of all SIM's in server */
1605         silc_dlist_add(server->sim, sim);
1606
1607         silc_free(alg_name);
1608       } else {
1609         SILC_LOG_ERROR(("Error configuring ciphers"));
1610         silc_sim_free(sim);
1611         silc_server_stop(server);
1612         exit(1);
1613       }
1614
1615       /* Register the cipher */
1616       silc_cipher_register(&cipher_obj);
1617 #else
1618       SILC_LOG_ERROR(("Dynamic module support not compiled, "
1619                         "can't load modules!"));
1620       silc_server_stop(server);
1621       exit(1);
1622 #endif
1623     }
1624     cipher = cipher->next;
1625   } /* while */
1626
1627   return TRUE;
1628 }
1629
1630 /* Registers configured hash functions. These can then be allocated by the
1631    server when needed. */
1632
1633 bool silc_server_config_register_hashfuncs(SilcServer server)
1634 {
1635   SilcServerConfig config = server->config;
1636   SilcServerConfigHash *hash = config->hash;
1637   char *module_path = config->module_path;
1638
1639   SILC_LOG_DEBUG(("Registering configured hash functions"));
1640
1641   if (!hash) /* any hash func in the config file? */
1642     return FALSE;
1643
1644   while (hash) {
1645     /* if there isn't a module_path OR there isn't a module sim name try to
1646      * use buil-in functions */
1647     if (!module_path || !hash->module) {
1648       int i;
1649       for (i = 0; silc_default_hash[i].name; i++)
1650         if (!strcmp(silc_default_hash[i].name, hash->name)) {
1651           silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1652           break;
1653         }
1654       if (!silc_hash_is_supported(hash->name)) {
1655         SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1656         silc_server_stop(server);
1657         exit(1);
1658       }
1659     } else {
1660 #ifdef SILC_SIM
1661       /* Load (try at least) the hash SIM module */
1662       SilcHashObject hash_obj;
1663       SilcSim sim;
1664
1665       memset(&hash_obj, 0, sizeof(hash_obj));
1666       hash_obj.name = hash->name;
1667       hash_obj.block_len = hash->block_length;
1668       hash_obj.hash_len = hash->digest_length;
1669
1670       sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1671
1672       if ((silc_sim_load(sim))) {
1673         hash_obj.init =
1674           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1675                                                 SILC_HASH_SIM_INIT));
1676         SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1677         hash_obj.update =
1678           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1679                                                 SILC_HASH_SIM_UPDATE));
1680         SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1681         hash_obj.final =
1682           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1683                                                 SILC_HASH_SIM_FINAL));
1684         SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1685         hash_obj.context_len =
1686           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1687                                                 SILC_HASH_SIM_CONTEXT_LEN));
1688         SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1689
1690         /* Put the SIM to the table of all SIM's in server */
1691         silc_dlist_add(server->sim, sim);
1692       } else {
1693         SILC_LOG_ERROR(("Error configuring hash functions"));
1694         silc_sim_free(sim);
1695         silc_server_stop(server);
1696         exit(1);
1697       }
1698
1699       /* Register the hash function */
1700       silc_hash_register(&hash_obj);
1701 #else
1702       SILC_LOG_ERROR(("Dynamic module support not compiled, "
1703                         "can't load modules!"));
1704       silc_server_stop(server);
1705       exit(1);
1706 #endif
1707     }
1708     hash = hash->next;
1709   } /* while */
1710
1711   return TRUE;
1712 }
1713
1714 /* Registers configure HMACs. These can then be allocated by the server
1715    when needed. */
1716
1717 bool silc_server_config_register_hmacs(SilcServer server)
1718 {
1719   SilcServerConfig config = server->config;
1720   SilcServerConfigHmac *hmac = config->hmac;
1721
1722   SILC_LOG_DEBUG(("Registering configured HMACs"));
1723
1724   if (!hmac)
1725     return FALSE;
1726
1727   while (hmac) {
1728     SilcHmacObject hmac_obj;
1729     if (!silc_hash_is_supported(hmac->hash)) {
1730       SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1731       silc_server_stop(server);
1732       exit(1);
1733     }
1734
1735     /* Register the HMAC */
1736     memset(&hmac_obj, 0, sizeof(hmac_obj));
1737     hmac_obj.name = hmac->name;
1738     hmac_obj.len = hmac->mac_length;
1739     silc_hmac_register(&hmac_obj);
1740
1741     hmac = hmac->next;
1742   } /* while */
1743
1744   return TRUE;
1745 }
1746
1747 /* Registers configured PKCS's. */
1748
1749 bool silc_server_config_register_pkcs(SilcServer server)
1750 {
1751   SilcServerConfig config = server->config;
1752   SilcServerConfigPkcs *pkcs = config->pkcs;
1753
1754   SILC_LOG_DEBUG(("Registering configured PKCS"));
1755
1756   if (!pkcs)
1757     return FALSE;
1758
1759   while (pkcs) {
1760     int i;
1761     for (i = 0; silc_default_pkcs[i].name; i++)
1762       if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1763         silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1764         break;
1765       }
1766     if (!silc_pkcs_is_supported(pkcs->name)) {
1767       SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1768       silc_server_stop(server);
1769       exit(1);
1770     }
1771     pkcs = pkcs->next;
1772   } /* while */
1773
1774   return TRUE;
1775 }
1776
1777 /* Sets log files where log messages are saved by the server logger. */
1778
1779 void silc_server_config_setlogfiles(SilcServer server)
1780 {
1781   SilcServerConfig config = server->config;
1782   SilcServerConfigLogging *this;
1783
1784   SILC_LOG_DEBUG(("Setting configured log file names and options"));
1785
1786   silc_log_timestamp = config->logging_timestamp;
1787   silc_log_quick = config->logging_quick;
1788   silc_log_flushdelay = (config->logging_flushdelay ?
1789                          config->logging_flushdelay :
1790                          SILC_SERVER_LOG_FLUSH_DELAY);
1791
1792   if ((this = config->logging_fatals))
1793     silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1794                       server->schedule);
1795   if ((this = config->logging_errors))
1796     silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1797                       server->schedule);
1798   if ((this = config->logging_warnings))
1799     silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1800                       server->schedule);
1801   if ((this = config->logging_info))
1802     silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1803                       server->schedule);
1804 }
1805
1806 /* Returns client authentication information from configuration file by host
1807    (name or ip) */
1808
1809 SilcServerConfigClient *
1810 silc_server_config_find_client(SilcServer server, char *host)
1811 {
1812   SilcServerConfig config = server->config;
1813   SilcServerConfigClient *client;
1814
1815   if (!config || !host)
1816     return NULL;
1817
1818   for (client = config->clients; client; client = client->next) {
1819     if (client->host && !silc_string_compare(client->host, host))
1820       continue;
1821     break;
1822   }
1823
1824   /* if none matched, then client is already NULL */
1825   return client;
1826 }
1827
1828 /* Returns admin connection configuration by host, username and/or
1829    nickname. */
1830
1831 SilcServerConfigAdmin *
1832 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1833                               char *nick)
1834 {
1835   SilcServerConfig config = server->config;
1836   SilcServerConfigAdmin *admin;
1837
1838   /* make sure we have a value for the matching parameters */
1839   if (!host)
1840     host = "*";
1841   if (!user)
1842     user = "*";
1843   if (!nick)
1844     nick = "*";
1845
1846   for (admin = config->admins; admin; admin = admin->next) {
1847     if (admin->host && !silc_string_compare(admin->host, host))
1848       continue;
1849     if (admin->user && !silc_string_compare(admin->user, user))
1850       continue;
1851     if (admin->nick && !silc_string_compare(admin->nick, nick))
1852       continue;
1853     /* no checks failed -> this entry matches */
1854     break;
1855   }
1856
1857   /* if none matched, then admin is already NULL */
1858   return admin;
1859 }
1860
1861 /* Returns the denied connection configuration entry by host. */
1862
1863 SilcServerConfigDeny *
1864 silc_server_config_find_denied(SilcServer server, char *host)
1865 {
1866   SilcServerConfig config = server->config;
1867   SilcServerConfigDeny *deny;
1868
1869   /* make sure we have a value for the matching parameters */
1870   if (!config || !host)
1871     return NULL;
1872
1873   for (deny = config->denied; deny; deny = deny->next) {
1874     if (deny->host && !silc_string_compare(deny->host, host))
1875       continue;
1876     break;
1877   }
1878
1879   /* if none matched, then deny is already NULL */
1880   return deny;
1881 }
1882
1883 /* Returns server connection info from server configuartion by host
1884    (name or ip). */
1885
1886 SilcServerConfigServer *
1887 silc_server_config_find_server_conn(SilcServer server, char *host)
1888 {
1889   SilcServerConfig config = server->config;
1890   SilcServerConfigServer *serv = NULL;
1891
1892   if (!host)
1893     return NULL;
1894
1895   if (!config->servers)
1896     return NULL;
1897
1898   for (serv = config->servers; serv; serv = serv->next) {
1899     if (!silc_string_compare(serv->host, host))
1900       continue;
1901     break;
1902   }
1903
1904   return serv;
1905 }
1906
1907 /* Returns router connection info from server configuration by
1908    host (name or ip). */
1909
1910 SilcServerConfigRouter *
1911 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1912 {
1913   SilcServerConfig config = server->config;
1914   SilcServerConfigRouter *serv = NULL;
1915
1916   if (!host)
1917     return NULL;
1918
1919   if (!config->routers)
1920     return NULL;
1921
1922   for (serv = config->routers; serv; serv = serv->next) {
1923     if (!silc_string_compare(serv->host, host))
1924       continue;
1925     if (port && serv->port && serv->port != port)
1926       continue;
1927     break;
1928   }
1929
1930   return serv;
1931 }
1932
1933 /* Find backup router connection by host (name or ip) */
1934
1935 SilcServerConfigRouter *
1936 silc_server_config_find_backup_conn(SilcServer server, char *host)
1937 {
1938   SilcServerConfig config = server->config;
1939   SilcServerConfigRouter *serv = NULL;
1940
1941   if (!host)
1942     return NULL;
1943
1944   if (!config->routers)
1945     return NULL;
1946
1947   for (serv = config->routers; serv; serv = serv->next) {
1948     if (!serv->backup_router)
1949       continue;
1950     if (!silc_string_compare(serv->host, host))
1951       continue;
1952     break;
1953   }
1954
1955   return serv;
1956 }
1957
1958 /* Returns TRUE if configuration for a router connection that we are
1959    initiating exists. */
1960
1961 bool silc_server_config_is_primary_route(SilcServer server)
1962 {
1963   SilcServerConfig config = server->config;
1964   SilcServerConfigRouter *serv = NULL;
1965   int i;
1966   bool found = FALSE;
1967
1968   serv = config->routers;
1969   for (i = 0; serv; i++) {
1970     if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1971       found = TRUE;
1972       break;
1973     }
1974
1975     serv = serv->next;
1976   }
1977
1978   return found;
1979 }
1980
1981 /* Returns our primary connection configuration or NULL if we do not
1982    have primary router configured. */
1983
1984 SilcServerConfigRouter *
1985 silc_server_config_get_primary_router(SilcServer server)
1986 {
1987   SilcServerConfig config = server->config;
1988   SilcServerConfigRouter *serv = NULL;
1989   int i;
1990
1991   serv = config->routers;
1992   for (i = 0; serv; i++) {
1993     if (serv->initiator == TRUE && serv->backup_router == FALSE)
1994       return serv;
1995     serv = serv->next;
1996   }
1997
1998   return NULL;
1999 }
2000
2001 /* If we have backup router configured that is going to replace us this
2002    function returns it. */
2003
2004 SilcServerConfigRouter *
2005 silc_server_config_get_backup_router(SilcServer server)
2006 {
2007   SilcServerConfig config = server->config;
2008   SilcServerConfigRouter *serv = NULL;
2009   int i;
2010
2011   if (server->server_type != SILC_ROUTER)
2012     return NULL;
2013
2014   serv = config->routers;
2015   for (i = 0; serv; i++) {
2016     if (serv->initiator == FALSE && serv->backup_router == TRUE &&
2017         serv->backup_local == TRUE &&
2018         !strcmp(server->config->server_info->primary->server_ip,
2019                 serv->backup_replace_ip) &&
2020         server->config->server_info->primary->port ==
2021         serv->backup_replace_port)
2022       return serv;
2023     serv = serv->next;
2024   }
2025
2026   return NULL;
2027 }