Merge commit 'origin/silc.1.1.branch'
[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 int 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 -1;
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       if (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 total;
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, "prefer_passphrase_auth")) {
237     config->prefer_passphrase_auth = *(SilcBool *)val;
238   }
239   else if (!strcmp(name, "require_reverse_lookup")) {
240     config->require_reverse_lookup = *(SilcBool *)val;
241   }
242   else if (!strcmp(name, "connections_max")) {
243     config->param.connections_max = (SilcUInt32) *(int *)val;
244   }
245   else if (!strcmp(name, "connections_max_per_host")) {
246     config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
247   }
248   else if (!strcmp(name, "keepalive_secs")) {
249     config->param.keepalive_secs = (SilcUInt32) *(int *)val;
250   }
251   else if (!strcmp(name, "reconnect_count")) {
252     config->param.reconnect_count = (SilcUInt32) *(int *)val;
253   }
254   else if (!strcmp(name, "reconnect_interval")) {
255     config->param.reconnect_interval = (SilcUInt32) *(int *)val;
256   }
257   else if (!strcmp(name, "reconnect_interval_max")) {
258     config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
259   }
260   else if (!strcmp(name, "reconnect_keep_trying")) {
261     config->param.reconnect_keep_trying = *(SilcBool *)val;
262   }
263   else if (!strcmp(name, "key_exchange_rekey")) {
264     config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
265   }
266   else if (!strcmp(name, "key_exchange_pfs")) {
267     config->param.key_exchange_pfs = *(SilcBool *)val;
268   }
269   else if (!strcmp(name, "channel_rekey_secs")) {
270     config->channel_rekey_secs = (SilcUInt32) *(int *)val;
271   }
272   else if (!strcmp(name, "key_exchange_timeout")) {
273     config->key_exchange_timeout = (SilcUInt32) *(int *)val;
274   }
275   else if (!strcmp(name, "conn_auth_timeout")) {
276     config->conn_auth_timeout = (SilcUInt32) *(int *)val;
277   }
278   else if (!strcmp(name, "version_protocol")) {
279     CONFIG_IS_DOUBLE(config->param.version_protocol);
280     config->param.version_protocol =
281       (*(char *)val ? strdup((char *) val) : NULL);
282   }
283   else if (!strcmp(name, "version_software")) {
284     CONFIG_IS_DOUBLE(config->param.version_software);
285     config->param.version_software =
286       (*(char *)val ? strdup((char *) val) : NULL);
287   }
288   else if (!strcmp(name, "version_software_vendor")) {
289     CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
290     config->param.version_software_vendor =
291       (*(char *)val ? strdup((char *) val) : NULL);
292   }
293   else if (!strcmp(name, "detach_disabled")) {
294     config->detach_disabled = *(SilcBool *)val;
295   }
296   else if (!strcmp(name, "detach_timeout")) {
297     config->detach_timeout = (SilcUInt32) *(int *)val;
298   }
299   else if (!strcmp(name, "qos")) {
300     config->param.qos = *(SilcBool *)val;
301   }
302   else if (!strcmp(name, "qos_rate_limit")) {
303     config->param.qos_rate_limit = *(SilcUInt32 *)val;
304   }
305   else if (!strcmp(name, "qos_bytes_limit")) {
306     config->param.qos_bytes_limit = *(SilcUInt32 *)val;
307   }
308   else if (!strcmp(name, "qos_limit_sec")) {
309     config->param.qos_limit_sec = *(SilcUInt32 *)val;
310   }
311   else if (!strcmp(name, "qos_limit_usec")) {
312     config->param.qos_limit_usec = *(SilcUInt32 *)val;
313   }
314   else if (!strcmp(name, "channel_join_limit")) {
315     config->param.chlimit = *(SilcUInt32 *)val;
316   }
317   else if (!strcmp(name, "debug_string")) {
318     CONFIG_IS_DOUBLE(config->debug_string);
319     config->debug_string = (*(char *)val ? strdup((char *) val) : NULL);
320   }
321   else if (!strcmp(name, "http_server")) {
322     config->httpd = *(SilcBool *)val;
323   }
324   else if (!strcmp(name, "http_server_ip")) {
325     CONFIG_IS_DOUBLE(config->httpd_ip);
326     config->httpd_ip = (*(char *)val ? strdup((char *) val) : NULL);
327   }
328   else if (!strcmp(name, "http_server_port")) {
329     int port = *(int *)val;
330     if ((port <= 0) || (port > 65535)) {
331       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
332                              "Invalid port number!"));
333       got_errno = SILC_CONFIG_EPRINTLINE;
334       goto got_err;
335     }
336     config->httpd_port = (SilcUInt16)port;
337   }
338   else if (!strcmp(name, "dynamic_server")) {
339     config->dynamic_server = *(SilcBool *)val;
340   }
341   else if (!strcmp(name, "local_channels")) {
342     config->local_channels = *(SilcBool *)val;
343   }
344   else
345     return SILC_CONFIG_EINTERNAL;
346
347   return SILC_CONFIG_OK;
348
349  got_err:
350   return got_errno;
351 }
352
353 SILC_CONFIG_CALLBACK(fetch_cipher)
354 {
355   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
356
357   SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
358                        type, name, context));
359   if (type == SILC_CONFIG_ARG_BLOCK) {
360     /* check the temporary struct's fields */
361     if (!tmp) /* discard empty sub-blocks */
362       return SILC_CONFIG_OK;
363     if (!tmp->name) {
364       got_errno = SILC_CONFIG_EMISSFIELDS;
365       goto got_err;
366     }
367
368     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
369     config->tmp = NULL;
370     return SILC_CONFIG_OK;
371   }
372   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
373
374   /* Identify and save this value */
375   if (!strcmp(name, "name")) {
376     CONFIG_IS_DOUBLE(tmp->name);
377     tmp->name = strdup((char *) val);
378   }
379   else if (!strcmp(name, "keylength")) {
380     tmp->key_length = *(SilcUInt32 *)val;
381   }
382   else if (!strcmp(name, "blocklength")) {
383     tmp->block_length = *(SilcUInt32 *)val;
384   }
385   else
386     return SILC_CONFIG_EINTERNAL;
387   return SILC_CONFIG_OK;
388
389  got_err:
390   silc_free(tmp->name);
391   silc_free(tmp);
392   config->tmp = NULL;
393   return got_errno;
394 }
395
396 SILC_CONFIG_CALLBACK(fetch_hash)
397 {
398   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
399
400   SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
401                        type, name, context));
402   if (type == SILC_CONFIG_ARG_BLOCK) {
403     /* check the temporary struct's fields */
404     if (!tmp) /* discard empty sub-blocks */
405       return SILC_CONFIG_OK;
406     if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
407       got_errno = SILC_CONFIG_EMISSFIELDS;
408       goto got_err;
409     }
410
411     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
412     config->tmp = NULL;
413     return SILC_CONFIG_OK;
414   }
415   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
416
417   /* Identify and save this value */
418   if (!strcmp(name, "name")) {
419     CONFIG_IS_DOUBLE(tmp->name);
420     tmp->name = strdup((char *) val);
421   }
422   else if (!strcmp(name, "blocklength")) {
423     tmp->block_length = *(int *)val;
424   }
425   else if (!strcmp(name, "digestlength")) {
426     tmp->digest_length = *(int *)val;
427   }
428   else
429     return SILC_CONFIG_EINTERNAL;
430   return SILC_CONFIG_OK;
431
432  got_err:
433   silc_free(tmp->name);
434   silc_free(tmp);
435   config->tmp = NULL;
436   return got_errno;
437 }
438
439 SILC_CONFIG_CALLBACK(fetch_hmac)
440 {
441   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
442
443   SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
444                        type, name, context));
445   if (type == SILC_CONFIG_ARG_BLOCK) {
446     /* check the temporary struct's fields */
447     if (!tmp) /* discard empty sub-blocks */
448       return SILC_CONFIG_OK;
449     if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
450       got_errno = SILC_CONFIG_EMISSFIELDS;
451       goto got_err;
452     }
453
454     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
455     config->tmp = NULL;
456     return SILC_CONFIG_OK;
457   }
458   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
459
460   /* Identify and save this value */
461   if (!strcmp(name, "name")) {
462     CONFIG_IS_DOUBLE(tmp->name);
463     tmp->name = strdup((char *) val);
464   }
465   else if (!strcmp(name, "hash")) {
466     CONFIG_IS_DOUBLE(tmp->hash);
467     tmp->hash = strdup((char *) val);
468   }
469   else if (!strcmp(name, "maclength")) {
470     tmp->mac_length = *(int *)val;
471   }
472   else
473     return SILC_CONFIG_EINTERNAL;
474   return SILC_CONFIG_OK;
475
476  got_err:
477   silc_free(tmp->name);
478   silc_free(tmp->hash);
479   silc_free(tmp);
480   config->tmp = NULL;
481   return got_errno;
482 }
483
484 SILC_CONFIG_CALLBACK(fetch_pkcs)
485 {
486   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
487
488   SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
489                        type, name, context));
490   if (type == SILC_CONFIG_ARG_BLOCK) {
491     /* Check the temporary struct's fields */
492     if (!tmp) /* discard empty sub-blocks */
493       return SILC_CONFIG_OK;
494     if (!tmp->name) {
495       got_errno = SILC_CONFIG_EMISSFIELDS;
496       goto got_err;
497     }
498
499     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
500     config->tmp = NULL;
501     return SILC_CONFIG_OK;
502   }
503   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
504
505   /* Identify and save this value */
506   if (!strcmp(name, "name")) {
507     CONFIG_IS_DOUBLE(tmp->name);
508     tmp->name = strdup((char *) val);
509   }
510   else
511     return SILC_CONFIG_EINTERNAL;
512   return SILC_CONFIG_OK;
513
514  got_err:
515   silc_free(tmp->name);
516   silc_free(tmp);
517   config->tmp = NULL;
518   return got_errno;
519 }
520
521 SILC_CONFIG_CALLBACK(fetch_serverinfo)
522 {
523   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
524   SilcServerConfigServerInfo *server_info = config->server_info;
525
526   SERVER_CONFIG_DEBUG(("Received SERVERINFO type=%d name=\"%s\" (val=%x)",
527                        type, name, context));
528
529   /* If there isn't the main struct alloc it */
530   if (!server_info)
531     config->server_info = server_info = (SilcServerConfigServerInfo *)
532                 silc_calloc(1, sizeof(*server_info));
533
534   if (type == SILC_CONFIG_ARG_BLOCK) {
535     if (!strcmp(name, "primary")) {
536       if (server_info->primary) {
537         SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
538                                "Double primary specification."));
539         got_errno = SILC_CONFIG_EPRINTLINE;
540         goto got_err;
541       }
542       CONFIG_IS_DOUBLE(server_info->primary);
543
544       /* now check the temporary struct, don't accept empty block and
545          make sure all fields are there */
546       if (!tmp || !tmp->server_ip || !tmp->port) {
547         got_errno = SILC_CONFIG_EMISSFIELDS;
548         goto got_err;
549       }
550       server_info->primary = tmp;
551       config->tmp = NULL;
552       return SILC_CONFIG_OK;
553     } else if (!strcmp(name, "secondary")) {
554       if (!tmp)
555         return SILC_CONFIG_OK;
556       if (!tmp || !tmp->server_ip || !tmp->port) {
557         got_errno = SILC_CONFIG_EMISSFIELDS;
558         goto got_err;
559       }
560       SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
561       config->tmp = NULL;
562       return SILC_CONFIG_OK;
563     } else if (!server_info->public_key || !server_info->private_key) {
564       got_errno = SILC_CONFIG_EMISSFIELDS;
565       goto got_err;
566     }
567     return SILC_CONFIG_OK;
568   }
569   if (!strcmp(name, "hostname")) {
570     CONFIG_IS_DOUBLE(server_info->server_name);
571     server_info->server_name = strdup((char *) val);
572   }
573   else if (!strcmp(name, "ip")) {
574     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
575     CONFIG_IS_DOUBLE(tmp->server_ip);
576     tmp->server_ip = strdup((char *) val);
577   }
578   else if (!strcmp(name, "public_ip")) {
579     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
580     CONFIG_IS_DOUBLE(tmp->public_ip);
581     tmp->public_ip = strdup((char *) val);
582   }
583   else if (!strcmp(name, "port")) {
584     int port = *(int *)val;
585     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
586     if ((port <= 0) || (port > 65535)) {
587       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
588                              "Invalid port number!"));
589       got_errno = SILC_CONFIG_EPRINTLINE;
590       goto got_err;
591     }
592     tmp->port = (SilcUInt16) port;
593   }
594   else if (!strcmp(name, "servertype")) {
595     CONFIG_IS_DOUBLE(server_info->server_type);
596     server_info->server_type = strdup((char *) val);
597   }
598   else if (!strcmp(name, "admin")) {
599     CONFIG_IS_DOUBLE(server_info->admin);
600     server_info->admin = strdup((char *) val);
601   }
602   else if (!strcmp(name, "adminemail")) {
603     CONFIG_IS_DOUBLE(server_info->email);
604     server_info->email = strdup((char *) val);
605   }
606   else if (!strcmp(name, "location")) {
607     CONFIG_IS_DOUBLE(server_info->location);
608     server_info->location = strdup((char *) val);
609   }
610   else if (!strcmp(name, "user")) {
611     CONFIG_IS_DOUBLE(server_info->user);
612     server_info->user = strdup((char *) val);
613   }
614   else if (!strcmp(name, "group")) {
615     CONFIG_IS_DOUBLE(server_info->group);
616     server_info->group = strdup((char *) val);
617   }
618   else if (!strcmp(name, "motdfile")) {
619     CONFIG_IS_DOUBLE(server_info->motd_file);
620     server_info->motd_file = strdup((char *) val);
621   }
622   else if (!strcmp(name, "pidfile")) {
623     CONFIG_IS_DOUBLE(server_info->pid_file);
624     server_info->pid_file = strdup((char *) val);
625   }
626   else if (!strcmp(name, "publickey")) {
627     char *file_tmp = (char *) val;
628     CONFIG_IS_DOUBLE(server_info->public_key);
629
630     /* Try to load specified file, if fail stop config parsing */
631     if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key)) {
632       SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
633       return SILC_CONFIG_EPRINTLINE;
634     }
635   }
636   else if (!strcmp(name, "privatekey")) {
637     struct stat st;
638     char *file_tmp = (char *) val;
639     CONFIG_IS_DOUBLE(server_info->private_key);
640
641     /* Check the private key file permissions. */
642     if ((stat(file_tmp, &st)) != -1) {
643       if (((st.st_mode & 0777) != 0600) &&
644           ((st.st_mode & 0777) != 0640)) {
645         SILC_SERVER_LOG_ERROR(("Wrong permissions in private key "
646                               "file \"%s\".  The permissions must be "
647                               "0600 or 0640.", file_tmp));
648         return SILC_CONFIG_ESILENT;
649       }
650     }
651
652     /* Try to load specified file, if fail stop config parsing */
653     if (!silc_pkcs_load_private_key(file_tmp, "", 0,
654                                     &server_info->private_key)) {
655       SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
656       return SILC_CONFIG_EPRINTLINE;
657     }
658   }
659   else
660     return SILC_CONFIG_EINTERNAL;
661   return SILC_CONFIG_OK;
662
663  got_err:
664   /* Here we need to check if tmp exists because this function handles
665    * misc data (multiple fields and single-only fields) */
666   if (tmp) {
667     silc_free(tmp->server_ip);
668     silc_free(tmp);
669     config->tmp = NULL;
670   }
671   return got_errno;
672 }
673
674 SILC_CONFIG_CALLBACK(fetch_logging)
675 {
676   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
677
678   if (!strcmp(name, "timestamp")) {
679     config->logging_timestamp = *(SilcBool *)val;
680   }
681   else if (!strcmp(name, "quicklogs")) {
682     config->logging_quick = *(SilcBool *)val;
683   }
684   else if (!strcmp(name, "flushdelay")) {
685     int flushdelay = *(int *)val;
686     if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
687       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
688                             "Invalid flushdelay value, use quicklogs if you "
689                             "want real-time logging."));
690       return SILC_CONFIG_EPRINTLINE;
691     }
692     config->logging_flushdelay = (long) flushdelay;
693   }
694
695   /* The following istances happens only in Logging's sub-blocks, a match
696      for the sub-block name means that you should store the filename/maxsize
697      temporary struct to the proper logging channel.
698      If we get a match for "file" or "maxsize" this means that we are inside
699      a sub-sub-block and it is safe to alloc a new tmp. */
700 #define FETCH_LOGGING_CHAN(__chan__, __member__)                \
701   else if (!strcmp(name, __chan__)) {                           \
702     if (!tmp) return SILC_CONFIG_OK;                            \
703     if (!tmp->file) {                                           \
704       got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err;        \
705     }                                                           \
706     config->__member__ = tmp;                                   \
707     config->tmp = NULL;                                         \
708   }
709   FETCH_LOGGING_CHAN("info", logging_info)
710   FETCH_LOGGING_CHAN("warnings", logging_warnings)
711   FETCH_LOGGING_CHAN("errors", logging_errors)
712   FETCH_LOGGING_CHAN("fatals", logging_fatals)
713 #undef FETCH_LOGGING_CHAN
714   else if (!strcmp(name, "file")) {
715     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
716     CONFIG_IS_DOUBLE(tmp->file);
717     tmp->file = strdup((char *) val);
718   }
719   else if (!strcmp(name, "size")) {
720     if (!tmp) {
721       config->tmp = silc_calloc(1, sizeof(*tmp));
722       tmp = (SilcServerConfigLogging *) config->tmp;
723     }
724     tmp->maxsize = *(SilcUInt32 *) val;
725   }
726   else
727     return SILC_CONFIG_EINTERNAL;
728   return SILC_CONFIG_OK;
729
730  got_err:
731   silc_free(tmp->file);
732   silc_free(tmp);
733   config->tmp = NULL;
734   return got_errno;
735 }
736
737 SILC_CONFIG_CALLBACK(fetch_connparam)
738 {
739   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
740
741   SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
742                        type, name, context));
743   if (type == SILC_CONFIG_ARG_BLOCK) {
744     /* check the temporary struct's fields */
745     if (!tmp) /* discard empty sub-blocks */
746       return SILC_CONFIG_OK;
747     if (!tmp->name) {
748       got_errno = SILC_CONFIG_EMISSFIELDS;
749       goto got_err;
750     }
751     /* Set defaults */
752     my_set_param_defaults(tmp, &config->param);
753
754     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
755     config->tmp = NULL;
756     return SILC_CONFIG_OK;
757   }
758   if (!tmp) {
759     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
760     tmp->reconnect_keep_trying = TRUE;
761   }
762
763   if (!strcmp(name, "name")) {
764     CONFIG_IS_DOUBLE(tmp->name);
765     tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
766   }
767   else if (!strcmp(name, "connections_max")) {
768     tmp->connections_max = *(SilcUInt32 *)val;
769   }
770   else if (!strcmp(name, "connections_max_per_host")) {
771     tmp->connections_max_per_host = *(SilcUInt32 *)val;
772   }
773   else if (!strcmp(name, "keepalive_secs")) {
774     tmp->keepalive_secs = *(SilcUInt32 *)val;
775   }
776   else if (!strcmp(name, "reconnect_count")) {
777     tmp->reconnect_count = *(SilcUInt32 *)val;
778   }
779   else if (!strcmp(name, "reconnect_interval")) {
780     tmp->reconnect_interval = *(SilcUInt32 *)val;
781   }
782   else if (!strcmp(name, "reconnect_interval_max")) {
783     tmp->reconnect_interval_max = *(SilcUInt32 *)val;
784   }
785   else if (!strcmp(name, "reconnect_keep_trying")) {
786     tmp->reconnect_keep_trying = *(SilcBool *)val;
787   }
788   else if (!strcmp(name, "key_exchange_rekey")) {
789     tmp->key_exchange_rekey = *(SilcUInt32 *)val;
790   }
791   else if (!strcmp(name, "key_exchange_pfs")) {
792     tmp->key_exchange_pfs = *(SilcBool *)val;
793   }
794   else if (!strcmp(name, "version_protocol")) {
795     CONFIG_IS_DOUBLE(tmp->version_protocol);
796     tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
797   }
798   else if (!strcmp(name, "version_software")) {
799     CONFIG_IS_DOUBLE(tmp->version_software);
800     tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
801   }
802   else if (!strcmp(name, "version_software_vendor")) {
803     CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
804     tmp->version_software_vendor =
805       (*(char *)val ? strdup((char *) val) : NULL);
806   }
807   else if (!strcmp(name, "anonymous")) {
808     tmp->anonymous = *(SilcBool *)val;
809   }
810   else if (!strcmp(name, "qos")) {
811     tmp->qos = *(SilcBool *)val;
812   }
813   else if (!strcmp(name, "qos_rate_limit")) {
814     tmp->qos_rate_limit = *(SilcUInt32 *)val;
815   }
816   else if (!strcmp(name, "qos_bytes_limit")) {
817     tmp->qos_bytes_limit = *(SilcUInt32 *)val;
818   }
819   else if (!strcmp(name, "qos_limit_sec")) {
820     tmp->qos_limit_sec = *(SilcUInt32 *)val;
821   }
822   else if (!strcmp(name, "qos_limit_usec")) {
823     tmp->qos_limit_usec = *(SilcUInt32 *)val;
824   }
825   else
826     return SILC_CONFIG_EINTERNAL;
827
828   return SILC_CONFIG_OK;
829
830  got_err:
831   silc_free(tmp->name);
832   silc_free(tmp);
833   config->tmp = NULL;
834   return got_errno;
835 }
836
837 SILC_CONFIG_CALLBACK(fetch_client)
838 {
839   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
840
841   SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
842                        type, name, context));
843
844   /* Alloc before block checking, because empty sub-blocks are welcome here */
845   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
846
847   if (type == SILC_CONFIG_ARG_BLOCK) {
848     /* empty sub-blocks are welcome */
849     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
850     config->tmp = NULL;
851     return SILC_CONFIG_OK;
852   }
853
854   /* Identify and save this value */
855   if (!strcmp(name, "host")) {
856     CONFIG_IS_DOUBLE(tmp->host);
857     tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
858   }
859   else if (!strcmp(name, "passphrase")) {
860     CONFIG_IS_DOUBLE(tmp->passphrase);
861     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
862                            (void *)&tmp->passphrase,
863                            &tmp->passphrase_len, 0, NULL)) {
864       got_errno = SILC_CONFIG_EPRINTLINE;
865       goto got_err;
866     }
867   }
868   else if (!strcmp(name, "publickey")) {
869     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
870                            (void *)&config->server->repository, NULL,
871                            SILC_SKR_USAGE_AUTH |
872                            SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
873       got_errno = SILC_CONFIG_EPRINTLINE;
874       goto got_err;
875     }
876     tmp->publickeys = TRUE;
877   }
878   else if (!strcmp(name, "publickeydir")) {
879     if (my_parse_publickeydir((char *) val,
880                               (void *)&config->server->repository,
881                               SILC_SKR_USAGE_AUTH |
882                               SILC_SKR_USAGE_KEY_AGREEMENT) < 0) {
883       got_errno = SILC_CONFIG_EPRINTLINE;
884       goto got_err;
885     }
886     tmp->publickeys = TRUE;
887   }
888   else if (!strcmp(name, "params")) {
889     CONFIG_IS_DOUBLE(tmp->param);
890     tmp->param = my_find_param(config, (char *) val);
891     if (!tmp->param) { /* error message already output */
892       got_errno = SILC_CONFIG_EPRINTLINE;
893       goto got_err;
894     }
895   }
896   else
897     return SILC_CONFIG_EINTERNAL;
898   return SILC_CONFIG_OK;
899
900  got_err:
901   silc_free(tmp->host);
902   CONFIG_FREE_AUTH(tmp);
903   silc_free(tmp);
904   config->tmp = NULL;
905   return got_errno;
906 }
907
908 SILC_CONFIG_CALLBACK(fetch_admin)
909 {
910   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
911
912   SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
913                        type, name, context));
914   if (type == SILC_CONFIG_ARG_BLOCK) {
915     /* check the temporary struct's fields */
916     if (!tmp) /* discard empty sub-blocks */
917       return SILC_CONFIG_OK;
918
919     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
920     config->tmp = NULL;
921     return SILC_CONFIG_OK;
922   }
923   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
924
925   /* Identify and save this value */
926   if (!strcmp(name, "host")) {
927     CONFIG_IS_DOUBLE(tmp->host);
928     tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
929   }
930   else if (!strcmp(name, "user")) {
931     CONFIG_IS_DOUBLE(tmp->user);
932     tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
933   }
934   else if (!strcmp(name, "nick")) {
935     CONFIG_IS_DOUBLE(tmp->nick);
936     tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
937   }
938   else if (!strcmp(name, "passphrase")) {
939     CONFIG_IS_DOUBLE(tmp->passphrase);
940     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
941                            (void *)&tmp->passphrase,
942                            &tmp->passphrase_len, 0, NULL)) {
943       got_errno = SILC_CONFIG_EPRINTLINE;
944       goto got_err;
945     }
946   }
947   else if (!strcmp(name, "publickey")) {
948     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
949                            (void *)&config->server->repository, NULL,
950                            SILC_SKR_USAGE_SERVICE_AUTHORIZATION, tmp)) {
951       got_errno = SILC_CONFIG_EPRINTLINE;
952       goto got_err;
953     }
954     tmp->publickeys = TRUE;
955   }
956   else
957     return SILC_CONFIG_EINTERNAL;
958   return SILC_CONFIG_OK;
959
960  got_err:
961   silc_free(tmp->host);
962   silc_free(tmp->user);
963   silc_free(tmp->nick);
964   CONFIG_FREE_AUTH(tmp);
965   silc_free(tmp);
966   config->tmp = NULL;
967   return got_errno;
968 }
969
970 SILC_CONFIG_CALLBACK(fetch_deny)
971 {
972   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
973
974   SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
975                        type, name, context));
976   if (type == SILC_CONFIG_ARG_BLOCK) {
977     /* check the temporary struct's fields */
978     if (!tmp) /* discard empty sub-blocks */
979       return SILC_CONFIG_OK;
980     if (!tmp->reason) {
981       got_errno = SILC_CONFIG_EMISSFIELDS;
982       goto got_err;
983     }
984
985     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
986     config->tmp = NULL;
987     return SILC_CONFIG_OK;
988   }
989   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
990
991   /* Identify and save this value */
992   if (!strcmp(name, "host")) {
993     CONFIG_IS_DOUBLE(tmp->host);
994     tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
995   }
996   else if (!strcmp(name, "reason")) {
997     CONFIG_IS_DOUBLE(tmp->reason);
998     tmp->reason = strdup((char *) val);
999   }
1000   else
1001     return SILC_CONFIG_EINTERNAL;
1002   return SILC_CONFIG_OK;
1003
1004  got_err:
1005   silc_free(tmp->host);
1006   silc_free(tmp->reason);
1007   silc_free(tmp);
1008   config->tmp = NULL;
1009   return got_errno;
1010 }
1011
1012 SILC_CONFIG_CALLBACK(fetch_server)
1013 {
1014   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
1015
1016   SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
1017                        type, name, context));
1018   if (type == SILC_CONFIG_ARG_BLOCK) {
1019     /* check the temporary struct's fields */
1020     if (!tmp) /* discard empty sub-blocks */
1021       return SILC_CONFIG_OK;
1022     if (!tmp->host) {
1023       got_errno = SILC_CONFIG_EMISSFIELDS;
1024       goto got_err;
1025     }
1026
1027     /* the temporary struct is ok, append it to the list */
1028     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
1029     config->tmp = NULL;
1030     return SILC_CONFIG_OK;
1031   }
1032   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
1033
1034   /* Identify and save this value */
1035   if (!strcmp(name, "host")) {
1036     CONFIG_IS_DOUBLE(tmp->host);
1037     tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
1038   }
1039   else if (!strcmp(name, "passphrase")) {
1040     CONFIG_IS_DOUBLE(tmp->passphrase);
1041     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1042                            (void *)&tmp->passphrase,
1043                            &tmp->passphrase_len, 0, NULL)) {
1044       got_errno = SILC_CONFIG_EPRINTLINE;
1045       goto got_err;
1046     }
1047   }
1048   else if (!strcmp(name, "publickey")) {
1049     CONFIG_IS_DOUBLE(tmp->publickeys);
1050     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1051                            (void *)&config->server->repository, NULL,
1052                            SILC_SKR_USAGE_AUTH |
1053                            SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
1054       got_errno = SILC_CONFIG_EPRINTLINE;
1055       goto got_err;
1056     }
1057     tmp->publickeys = TRUE;
1058   }
1059   else if (!strcmp(name, "params")) {
1060     CONFIG_IS_DOUBLE(tmp->param);
1061     tmp->param = my_find_param(config, (char *) val);
1062     if (!tmp->param) { /* error message already output */
1063       got_errno = SILC_CONFIG_EPRINTLINE;
1064       goto got_err;
1065     }
1066   }
1067   else if (!strcmp(name, "backup")) {
1068     tmp->backup_router = *(SilcBool *)val;
1069   }
1070   else
1071     return SILC_CONFIG_EINTERNAL;
1072
1073   return SILC_CONFIG_OK;
1074
1075  got_err:
1076   silc_free(tmp->host);
1077   CONFIG_FREE_AUTH(tmp);
1078   silc_free(tmp);
1079   config->tmp = NULL;
1080   return got_errno;
1081 }
1082
1083 SILC_CONFIG_CALLBACK(fetch_router)
1084 {
1085   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
1086
1087   SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
1088                        type, name, context));
1089   if (type == SILC_CONFIG_ARG_BLOCK) {
1090     if (!tmp) /* discard empty sub-blocks */
1091       return SILC_CONFIG_OK;
1092     if (!tmp->host) {
1093       got_errno = SILC_CONFIG_EMISSFIELDS;
1094       goto got_err;
1095     }
1096
1097     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
1098     config->tmp = NULL;
1099     return SILC_CONFIG_OK;
1100   }
1101   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
1102
1103   /* Identify and save this value */
1104   if (!strcmp(name, "host")) {
1105     CONFIG_IS_DOUBLE(tmp->host);
1106     tmp->host = strdup((char *) val);
1107   }
1108   else if (!strcmp(name, "port")) {
1109     int port = *(int *)val;
1110     if ((port <= 0) || (port > 65535)) {
1111       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1112                              "Invalid port number!"));
1113       got_errno = SILC_CONFIG_EPRINTLINE;
1114       goto got_err;
1115     }
1116     tmp->port = (SilcUInt16) port;
1117   }
1118   else if (!strcmp(name, "passphrase")) {
1119     CONFIG_IS_DOUBLE(tmp->passphrase);
1120     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1121                            (void *)&tmp->passphrase,
1122                            &tmp->passphrase_len, 0, NULL)) {
1123       got_errno = SILC_CONFIG_EPRINTLINE;
1124       goto got_err;
1125     }
1126   }
1127   else if (!strcmp(name, "publickey")) {
1128     CONFIG_IS_DOUBLE(tmp->publickeys);
1129     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1130                            (void *)&config->server->repository, NULL,
1131                            SILC_SKR_USAGE_AUTH |
1132                            SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
1133       got_errno = SILC_CONFIG_EPRINTLINE;
1134       goto got_err;
1135     }
1136     tmp->publickeys = TRUE;
1137   }
1138   else if (!strcmp(name, "params")) {
1139     CONFIG_IS_DOUBLE(tmp->param);
1140     tmp->param = my_find_param(config, (char *) val);
1141     if (!tmp->param) { /* error message already output */
1142       got_errno = SILC_CONFIG_EPRINTLINE;
1143       goto got_err;
1144     }
1145   }
1146   else if (!strcmp(name, "initiator")) {
1147     tmp->initiator = *(SilcBool *)val;
1148   }
1149   else if (!strcmp(name, "backuphost")) {
1150     CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
1151     tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
1152                               strdup("*"));
1153     tmp->backup_router = TRUE;
1154   }
1155   else if (!strcmp(name, "backupport")) {
1156     int port = *(int *)val;
1157     if ((port <= 0) || (port > 65535)) {
1158       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1159                              "Invalid port number!"));
1160       got_errno = SILC_CONFIG_EPRINTLINE;
1161       goto got_err;
1162     }
1163     tmp->backup_replace_port = (SilcUInt16) port;
1164   }
1165   else if (!strcmp(name, "backuplocal")) {
1166     tmp->backup_local = *(SilcBool *)val;
1167   }
1168   else if (!strcmp(name, "dynamic_connection")) {
1169     tmp->dynamic_connection = *(SilcBool *)val;
1170   }
1171   else
1172     return SILC_CONFIG_EINTERNAL;
1173
1174   return SILC_CONFIG_OK;
1175
1176  got_err:
1177   silc_free(tmp->host);
1178   silc_free(tmp->backup_replace_ip);
1179   CONFIG_FREE_AUTH(tmp);
1180   silc_free(tmp);
1181   config->tmp = NULL;
1182   return got_errno;
1183 }
1184
1185 /* known config options tables */
1186 static const SilcConfigTable table_general[] = {
1187   { "prefer_passphrase_auth",   SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1188   { "require_reverse_lookup",   SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1189   { "connections_max",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1190   { "connections_max_per_host", SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1191   { "keepalive_secs",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1192   { "reconnect_count",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1193   { "reconnect_interval",       SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1194   { "reconnect_interval_max",   SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1195   { "reconnect_keep_trying",    SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1196   { "key_exchange_rekey",       SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1197   { "key_exchange_pfs",         SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1198   { "channel_rekey_secs",       SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1199   { "key_exchange_timeout",     SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1200   { "conn_auth_timeout",        SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1201   { "version_protocol",         SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
1202   { "version_software",         SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
1203   { "version_software_vendor",  SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
1204   { "detach_disabled",          SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1205   { "detach_timeout",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1206   { "qos",                      SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1207   { "qos_rate_limit",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1208   { "qos_bytes_limit",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1209   { "qos_limit_sec",            SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1210   { "qos_limit_usec",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1211   { "channel_join_limit",       SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1212   { "debug_string",             SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
1213   { "http_server",              SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1214   { "http_server_ip",           SILC_CONFIG_ARG_STRE,   fetch_generic,  NULL },
1215   { "http_server_port",         SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1216   { "dynamic_server",           SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1217   { "local_channels",           SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1218   { 0, 0, 0, 0 }
1219 };
1220
1221 static const SilcConfigTable table_cipher[] = {
1222   { "name",             SILC_CONFIG_ARG_STR,    fetch_cipher,   NULL },
1223   { "keylength",        SILC_CONFIG_ARG_INT,    fetch_cipher,   NULL },
1224   { "blocklength",      SILC_CONFIG_ARG_INT,    fetch_cipher,   NULL },
1225   { 0, 0, 0, 0 }
1226 };
1227
1228 static const SilcConfigTable table_hash[] = {
1229   { "name",             SILC_CONFIG_ARG_STR,    fetch_hash,     NULL },
1230   { "blocklength",      SILC_CONFIG_ARG_INT,    fetch_hash,     NULL },
1231   { "digestlength",     SILC_CONFIG_ARG_INT,    fetch_hash,     NULL },
1232   { 0, 0, 0, 0 }
1233 };
1234
1235 static const SilcConfigTable table_hmac[] = {
1236   { "name",             SILC_CONFIG_ARG_STR,    fetch_hmac,     NULL },
1237   { "hash",             SILC_CONFIG_ARG_STR,    fetch_hmac,     NULL },
1238   { "maclength",        SILC_CONFIG_ARG_INT,    fetch_hmac,     NULL },
1239   { 0, 0, 0, 0 }
1240 };
1241
1242 static const SilcConfigTable table_pkcs[] = {
1243   { "name",             SILC_CONFIG_ARG_STR,    fetch_pkcs,     NULL },
1244   { 0, 0, 0, 0 }
1245 };
1246
1247 static const SilcConfigTable table_serverinfo_c[] = {
1248   { "ip",               SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1249   { "public_ip",        SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1250   { "port",             SILC_CONFIG_ARG_INT,    fetch_serverinfo, NULL},
1251   { 0, 0, 0, 0 }
1252 };
1253
1254 static const SilcConfigTable table_serverinfo[] = {
1255   { "hostname",         SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1256   { "primary",          SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo_c},
1257   { "secondary",        SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo_c},
1258   { "servertype",       SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1259   { "location",         SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1260   { "admin",            SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1261   { "adminemail",       SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1262   { "user",             SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1263   { "group",            SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1264   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1265   { "privatekey",       SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1266   { "motdfile",         SILC_CONFIG_ARG_STRE,   fetch_serverinfo, NULL},
1267   { "pidfile",          SILC_CONFIG_ARG_STRE,   fetch_serverinfo, NULL},
1268   { 0, 0, 0, 0 }
1269 };
1270
1271 static const SilcConfigTable table_logging_c[] = {
1272   { "file",             SILC_CONFIG_ARG_STR,    fetch_logging,  NULL },
1273   { "size",             SILC_CONFIG_ARG_SIZE,   fetch_logging,  NULL },
1274 /*{ "quicklog",         SILC_CONFIG_ARG_NONE,   fetch_logging,  NULL }, */
1275   { 0, 0, 0, 0 }
1276 };
1277
1278 static const SilcConfigTable table_logging[] = {
1279   { "timestamp",        SILC_CONFIG_ARG_TOGGLE, fetch_logging,  NULL },
1280   { "quicklogs",        SILC_CONFIG_ARG_TOGGLE, fetch_logging,  NULL },
1281   { "flushdelay",       SILC_CONFIG_ARG_INT,    fetch_logging,  NULL },
1282   { "info",             SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1283   { "warnings",         SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1284   { "errors",           SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1285   { "fatals",           SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1286   { 0, 0, 0, 0 }
1287 };
1288
1289 static const SilcConfigTable table_connparam[] = {
1290   { "name",                    SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1291   { "require_reverse_lookup",  SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1292   { "connections_max",         SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1293   { "connections_max_per_host",SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1294   { "keepalive_secs",          SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1295   { "reconnect_count",         SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1296   { "reconnect_interval",      SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1297   { "reconnect_interval_max",  SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1298   { "reconnect_keep_trying",   SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1299   { "key_exchange_rekey",      SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1300   { "key_exchange_pfs",        SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1301   { "version_protocol",        SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1302   { "version_software",        SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1303   { "version_software_vendor", SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1304   { "anonymous",               SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1305   { "qos",                     SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1306   { "qos_rate_limit",          SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1307   { "qos_bytes_limit",         SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1308   { "qos_limit_sec",           SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1309   { "qos_limit_usec",          SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1310   { 0, 0, 0, 0 }
1311 };
1312
1313 static const SilcConfigTable table_client[] = {
1314   { "host",             SILC_CONFIG_ARG_STRE,   fetch_client,   NULL },
1315   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1316   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1317   { "publickeydir",     SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1318   { "params",           SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1319   { 0, 0, 0, 0 }
1320 };
1321
1322 static const SilcConfigTable table_admin[] = {
1323   { "host",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1324   { "user",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1325   { "nick",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1326   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1327   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1328   { "port",             SILC_CONFIG_ARG_INT,    fetch_admin,    NULL },
1329   { "params",           SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1330   { 0, 0, 0, 0 }
1331 };
1332
1333 static const SilcConfigTable table_deny[] = {
1334   { "host",             SILC_CONFIG_ARG_STRE,   fetch_deny,     NULL },
1335   { "reason",           SILC_CONFIG_ARG_STR,    fetch_deny,     NULL },
1336   { 0, 0, 0, 0 }
1337 };
1338
1339 static const SilcConfigTable table_serverconn[] = {
1340   { "host",             SILC_CONFIG_ARG_STRE,   fetch_server,   NULL },
1341   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1342   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1343   { "params",           SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1344   { "backup",           SILC_CONFIG_ARG_TOGGLE, fetch_server,   NULL },
1345   { 0, 0, 0, 0 }
1346 };
1347
1348 static const SilcConfigTable table_routerconn[] = {
1349   { "host",             SILC_CONFIG_ARG_STRE,   fetch_router,   NULL },
1350   { "port",             SILC_CONFIG_ARG_INT,    fetch_router,   NULL },
1351   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1352   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1353   { "params",           SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1354   { "initiator",        SILC_CONFIG_ARG_TOGGLE, fetch_router,   NULL },
1355   { "backuphost",       SILC_CONFIG_ARG_STRE,   fetch_router,   NULL },
1356   { "backupport",       SILC_CONFIG_ARG_INT,    fetch_router,   NULL },
1357   { "backuplocal",      SILC_CONFIG_ARG_TOGGLE, fetch_router,   NULL },
1358   { "dynamic_connection",       SILC_CONFIG_ARG_TOGGLE, fetch_router,   NULL },
1359   { 0, 0, 0, 0 }
1360 };
1361
1362 static const SilcConfigTable table_main[] = {
1363   { "cipher",           SILC_CONFIG_ARG_BLOCK,  fetch_cipher,  table_cipher },
1364   { "hash",             SILC_CONFIG_ARG_BLOCK,  fetch_hash,    table_hash },
1365   { "hmac",             SILC_CONFIG_ARG_BLOCK,  fetch_hmac,    table_hmac },
1366   { "pkcs",             SILC_CONFIG_ARG_BLOCK,  fetch_pkcs,    table_pkcs },
1367   { "general",          SILC_CONFIG_ARG_BLOCK,  NULL,          table_general },
1368   { "serverinfo",       SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo },
1369   { "logging",          SILC_CONFIG_ARG_BLOCK,  NULL,          table_logging },
1370   { "connectionparams", SILC_CONFIG_ARG_BLOCK,  fetch_connparam, table_connparam },
1371   { "client",           SILC_CONFIG_ARG_BLOCK,  fetch_client,  table_client },
1372   { "admin",            SILC_CONFIG_ARG_BLOCK,  fetch_admin,   table_admin },
1373   { "deny",             SILC_CONFIG_ARG_BLOCK,  fetch_deny,    table_deny },
1374   { "serverconnection", SILC_CONFIG_ARG_BLOCK,  fetch_server,  table_serverconn },
1375   { "routerconnection", SILC_CONFIG_ARG_BLOCK,  fetch_router,  table_routerconn },
1376   { 0, 0, 0, 0 }
1377 };
1378
1379 /* Set default values to stuff that was not configured. */
1380
1381 static void silc_server_config_set_defaults(SilcServerConfig config)
1382 {
1383   my_set_param_defaults(&config->param, NULL);
1384
1385   config->channel_rekey_secs = (config->channel_rekey_secs ?
1386                                 config->channel_rekey_secs :
1387                                 SILC_SERVER_CHANNEL_REKEY);
1388   config->key_exchange_timeout = (config->key_exchange_timeout ?
1389                                   config->key_exchange_timeout :
1390                                   SILC_SERVER_SKE_TIMEOUT);
1391   config->conn_auth_timeout = (config->conn_auth_timeout ?
1392                                config->conn_auth_timeout :
1393                                SILC_SERVER_CONNAUTH_TIMEOUT);
1394 }
1395
1396 /* Check for correctness of the configuration */
1397
1398 static SilcBool silc_server_config_check(SilcServerConfig config)
1399 {
1400   SilcBool ret = TRUE;
1401   SilcServerConfigServer *s;
1402   SilcServerConfigRouter *r;
1403   SilcBool b = FALSE;
1404
1405   /* ServerConfig is mandatory */
1406   if (!config->server_info) {
1407     SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `ServerInfo'"));
1408     ret = FALSE;
1409   }
1410
1411   if (!config->server_info->public_key ||
1412       !config->server_info->private_key) {
1413     SILC_SERVER_LOG_ERROR(("\nError: Server keypair is missing"));
1414     ret = FALSE;
1415   }
1416
1417   if (!config->server_info->primary) {
1418     SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `Primary' "
1419                            "in `ServerInfo'"));
1420     ret = FALSE;
1421   }
1422
1423   if (!config->server_info->primary->server_ip) {
1424     SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory field `Ip' "
1425                            "in `Primary' in `ServerInfo'"));
1426     ret = FALSE;
1427   }
1428
1429   /* RouterConnection sanity checks */
1430
1431   if (config->routers && config->routers->backup_router == TRUE &&
1432       !config->servers) {
1433     SILC_SERVER_LOG_ERROR((
1434          "\nError: First RouterConnection block must be primary router "
1435          "connection. You have marked it incorrectly as backup router."));
1436     ret = FALSE;
1437   }
1438   if (config->routers && config->routers->backup_router == TRUE &&
1439       !config->servers && !config->routers->next) {
1440     SILC_SERVER_LOG_ERROR((
1441          "\nError: You have configured backup router but not primary router. "
1442          "If backup router is configured also primary router must be "
1443          "configured."));
1444     ret = FALSE;
1445   }
1446
1447   /* Backup router sanity checks */
1448
1449   for (r = config->routers; r; r = r->next) {
1450     if (r->backup_router && !strcmp(r->host, r->backup_replace_ip)) {
1451       SILC_SERVER_LOG_ERROR((
1452           "\nError: Backup router connection incorrectly configured to use "
1453           "primary and backup router as same host `%s'. They must not be "
1454           "same host.", r->host));
1455       ret = FALSE;
1456     }
1457
1458     if (r->initiator == FALSE && r->port != 0) {
1459       SILC_SERVER_LOG_WARNING(("\nWarning: Initiator is FALSE and Port is "
1460                                "specified. Ignoring Port value."));
1461       r->port = 0;
1462     }
1463   }
1464
1465   /* ServerConnection sanity checks */
1466
1467   for (s = config->servers; s; s = s->next) {
1468     if (s->backup_router) {
1469       b = TRUE;
1470       break;
1471     }
1472   }
1473   if (b) {
1474     for (s = config->servers; s; s = s->next) {
1475       if (!s->backup_router) {
1476         SILC_SERVER_LOG_ERROR((
1477           "\nError: Your server is backup router but not all ServerConnection "
1478           "blocks were marked as backup connections. They all must be "
1479           "marked as backup connections."));
1480         ret = FALSE;
1481         break;
1482       }
1483     }
1484   }
1485
1486   return ret;
1487 }
1488
1489 /* Allocates a new configuration object, opens configuration file and
1490    parses it. The parsed data is returned to the newly allocated
1491    configuration object. The SilcServerConfig must be freed by calling
1492    the silc_server_config_destroy function. */
1493
1494 SilcServerConfig silc_server_config_alloc(const char *filename,
1495                                           SilcServer server)
1496 {
1497   SilcServerConfig config_new;
1498   SilcConfigEntity ent;
1499   SilcConfigFile *file;
1500   int ret;
1501   SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1502
1503   /* alloc a config object */
1504   config_new = silc_calloc(1, sizeof(*config_new));
1505   if (!config_new)
1506     return NULL;
1507
1508   /* general config defaults */
1509   config_new->refcount = 1;
1510   config_new->logging_timestamp = TRUE;
1511   config_new->param.reconnect_keep_trying = TRUE;
1512   config_new->server = server;
1513
1514   /* obtain a config file object */
1515   file = silc_config_open(filename);
1516   if (!file) {
1517     SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
1518                            filename));
1519     return NULL;
1520   }
1521
1522   /* obtain a SilcConfig entity, we can use it to start the parsing */
1523   ent = silc_config_init(file);
1524
1525   /* load the known configuration options, give our empty object as context */
1526   silc_config_register_table(ent, table_main, (void *) config_new);
1527
1528   /* enter the main parsing loop.  When this returns, we have the parsing
1529    * result and the object filled (or partially, in case of errors). */
1530   ret = silc_config_main(ent);
1531   SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1532                   silc_config_strerror(ret)));
1533
1534   /* Check if the parser returned errors */
1535   if (ret) {
1536     /* handle this special error return which asks to quietly return */
1537     if (ret != SILC_CONFIG_ESILENT) {
1538       char *linebuf, *filename = silc_config_get_filename(file);
1539       SilcUInt32 line = silc_config_get_line(file);
1540       if (ret != SILC_CONFIG_EPRINTLINE)
1541         SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
1542                                silc_config_strerror(ret)));
1543       linebuf = silc_config_read_line(file, line);
1544       if (linebuf) {
1545         SILC_SERVER_LOG_ERROR(("  file %s line %lu:  %s\n", filename,
1546                                line, linebuf));
1547         silc_free(linebuf);
1548       }
1549     }
1550     silc_server_config_destroy(config_new);
1551     silc_config_close(file);
1552     return NULL;
1553   }
1554
1555   /* close (destroy) the file object */
1556   silc_config_close(file);
1557
1558   /* Check the configuration */
1559   if (!silc_server_config_check(config_new)) {
1560     silc_server_config_destroy(config_new);
1561     return NULL;
1562   }
1563
1564   /* Set default to configuration parameters */
1565   silc_server_config_set_defaults(config_new);
1566
1567   return config_new;
1568 }
1569
1570 /* Increments the reference counter of a config object */
1571
1572 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1573                             void *ref_ptr)
1574 {
1575   if (ref_ptr) {
1576     config->refcount++;
1577     ref->config = config;
1578     ref->ref_ptr = ref_ptr;
1579     SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1580                     config->refcount - 1, config->refcount));
1581   }
1582 }
1583
1584 /* Decrements the reference counter of a config object.  If the counter
1585    reaches 0, the config object is destroyed. */
1586
1587 void silc_server_config_unref(SilcServerConfigRef *ref)
1588 {
1589   if (ref->ref_ptr)
1590     silc_server_config_destroy(ref->config);
1591 }
1592
1593 /* Destroy a config object with all his children lists */
1594
1595 void silc_server_config_destroy(SilcServerConfig config)
1596 {
1597   void *tmp;
1598
1599   config->refcount--;
1600   SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1601                   config->refcount + 1, config->refcount));
1602   if (config->refcount > 0)
1603     return;
1604
1605   SILC_LOG_DEBUG(("Freeing config context"));
1606
1607   /* Destroy general config stuff */
1608   silc_free(config->debug_string);
1609   silc_free(config->param.version_protocol);
1610   silc_free(config->param.version_software);
1611   silc_free(config->param.version_software_vendor);
1612   silc_free(config->httpd_ip);
1613
1614   /* Destroy Logging channels */
1615   if (config->logging_info)
1616     silc_free(config->logging_info->file);
1617   if (config->logging_warnings)
1618     silc_free(config->logging_warnings->file);
1619   if (config->logging_errors)
1620     silc_free(config->logging_errors->file);
1621   if (config->logging_fatals)
1622     silc_free(config->logging_fatals->file);
1623   silc_free(config->logging_info);
1624   silc_free(config->logging_warnings);
1625   silc_free(config->logging_errors);
1626   silc_free(config->logging_fatals);
1627
1628   /* Destroy the ServerInfo struct */
1629   if (config->server_info) {
1630     register SilcServerConfigServerInfo *si = config->server_info;
1631     silc_free(si->server_name);
1632     if (si->primary) {
1633       silc_free(si->primary->server_ip);
1634       silc_free(si->primary);
1635     }
1636     SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1637                                   si->secondary)
1638       silc_free(di->server_ip);
1639       silc_free(di);
1640     }
1641     silc_free(si->server_type);
1642     silc_free(si->location);
1643     silc_free(si->admin);
1644     silc_free(si->email);
1645     silc_free(si->user);
1646     silc_free(si->group);
1647     silc_free(si->motd_file);
1648     silc_free(si->pid_file);
1649     if (si->public_key)
1650       silc_pkcs_public_key_free(si->public_key);
1651     if (si->private_key)
1652       silc_pkcs_private_key_free(si->private_key);
1653     silc_free(si);
1654   }
1655
1656   /* Now let's destroy the lists */
1657
1658   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1659                                   config->cipher)
1660     silc_free(di->name);
1661     silc_free(di);
1662   }
1663   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1664     silc_free(di->name);
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 }