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