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