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