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