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