5 Author: Giovanni Giacobbi <giovanni@giacobbi.net>
7 Copyright (C) 1997 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
26 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
28 #define SERVER_CONFIG_DEBUG(fmt)
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; \
37 /* allocate the tmp field for fetching data */
38 #define SILC_SERVER_CONFIG_ALLOCTMP(__type__) \
40 config->tmp = silc_calloc(1, sizeof(*findtmp)); \
41 tmp = (__type__ *) config->tmp; \
44 /* append the tmp field to the specified list */
45 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \
49 for (findtmp = __list__; findtmp->next; findtmp = findtmp->next); \
50 findtmp->next = tmp; \
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;
60 /* Set EDOUBLE error value and bail out if necessary */
61 #define CONFIG_IS_DOUBLE(__x__) \
63 got_errno = SILC_CONFIG_EDOUBLE; \
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);
72 /* Set default values to those parameters that have not been defined */
74 my_set_param_defaults(SilcServerConfigConnParams *params,
75 SilcServerConfigConnParams *defaults)
77 #define SET_PARAM_DEFAULT(p, d) params->p = \
78 (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
80 SET_PARAM_DEFAULT(connections_max, SILC_SERVER_MAX_CONNECTIONS);
81 SET_PARAM_DEFAULT(connections_max_per_host,
82 SILC_SERVER_MAX_CONNECTIONS_SINGLE);
83 SET_PARAM_DEFAULT(keepalive_secs, SILC_SERVER_KEEPALIVE);
84 SET_PARAM_DEFAULT(reconnect_count, SILC_SERVER_RETRY_COUNT);
85 SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
86 SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
87 SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
88 SET_PARAM_DEFAULT(qos_rate_limit, SILC_SERVER_QOS_RATE_LIMIT);
89 SET_PARAM_DEFAULT(qos_bytes_limit, SILC_SERVER_QOS_BYTES_LIMIT);
90 SET_PARAM_DEFAULT(qos_limit_sec, SILC_SERVER_QOS_LIMIT_SEC);
91 SET_PARAM_DEFAULT(qos_limit_usec, SILC_SERVER_QOS_LIMIT_USEC);
92 SET_PARAM_DEFAULT(chlimit, SILC_SERVER_CH_JOIN_LIMIT);
94 #undef SET_PARAM_DEFAULT
97 /* Find connection parameters by the parameter block name. */
98 static SilcServerConfigConnParams *
99 my_find_param(SilcServerConfig config, const char *name)
101 SilcServerConfigConnParams *param;
103 for (param = config->conn_params; param; param = param->next) {
104 if (!strcasecmp(param->name, name))
108 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
109 "Cannot find Params \"%s\".", name));
114 /* SKR find callbcak */
116 static void my_find_callback(SilcSKR skr, SilcSKRFind find,
117 SilcSKRStatus status, SilcDList keys,
120 SilcSKRStatus *s = context;
124 silc_dlist_uninit(keys);
126 silc_skr_find_free(find);
129 /* parse an authdata according to its auth method */
130 static SilcBool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
131 void **auth_data, SilcUInt32 *auth_data_len,
132 SilcSKRKeyUsage usage, void *key_context)
134 if (auth_meth == SILC_AUTH_PASSWORD) {
135 /* p is a plain text password */
136 if (auth_data && auth_data_len) {
137 if (!silc_utf8_valid(p, strlen(p))) {
138 *auth_data_len = silc_utf8_encoded_len(p, strlen(p),
140 *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
141 silc_utf8_encode(p, strlen(p), SILC_STRING_LOCALE, *auth_data,
144 *auth_data = (void *) strdup(p);
145 *auth_data_len = (SilcUInt32) strlen(p);
148 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
149 /* p is a public key file name */
150 SilcPublicKey public_key;
151 SilcSKR skr = *auth_data;
153 SilcSKRStatus status;
155 if (!silc_pkcs_load_public_key(p, &public_key)) {
156 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
157 "Could not load public key file!"));
161 find = silc_skr_find_alloc();
162 silc_skr_find_set_public_key(find, public_key);
163 silc_skr_find_set_usage(find, usage);
164 silc_skr_find_set_context(find, key_context ? key_context : (void *)usage);
165 silc_skr_find(skr, NULL, find, my_find_callback, &status);
166 if (status != SILC_SKR_OK) {
167 silc_pkcs_public_key_free(public_key);
168 SILC_SERVER_LOG_WARNING(("Warning: public key file \"%s\" already "
169 "configured, ignoring this key", p));
170 return TRUE; /* non fatal error */
173 /* Add the public key to repository */
174 if (silc_skr_add_public_key(skr, public_key, usage,
175 key_context ? key_context : (void *)usage) !=
177 SILC_SERVER_LOG_ERROR(("Error while adding public key \"%s\"", p));
185 static SilcBool my_parse_publickeydir(const char *dirname, void **auth_data,
186 SilcSKRKeyUsage usage)
189 struct dirent *get_file;
192 if (!(dp = opendir(dirname))) {
193 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
194 "Could not open directory \"%s\"", dirname));
198 /* errors are not considered fatal */
199 while ((get_file = readdir(dp))) {
200 const char *filename = get_file->d_name;
202 int dirname_len = strlen(dirname), filename_len = strlen(filename);
203 struct stat check_file;
205 /* Ignore "." and "..", and take files only with ".pub" suffix. */
206 if (!strcmp(filename, ".") || !strcmp(filename, "..") ||
207 (filename_len < 5) || strcmp(filename + filename_len - 4, ".pub"))
210 memset(buf, 0, sizeof(buf));
211 snprintf(buf, sizeof(buf) - 1, "%s%s%s", dirname,
212 (dirname[dirname_len - 1] == '/' ? "" : "/"), filename);
214 if (stat(buf, &check_file) < 0) {
215 SILC_SERVER_LOG_ERROR(("Error stating file %s: %s", buf,
217 } else if (S_ISREG(check_file.st_mode)) {
218 my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL,
224 SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname));
230 SILC_CONFIG_CALLBACK(fetch_generic)
232 SilcServerConfig config = (SilcServerConfig) context;
235 if (!strcmp(name, "module_path")) {
236 CONFIG_IS_DOUBLE(config->module_path);
237 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
239 else if (!strcmp(name, "prefer_passphrase_auth")) {
240 config->prefer_passphrase_auth = *(SilcBool *)val;
242 else if (!strcmp(name, "require_reverse_lookup")) {
243 config->require_reverse_lookup = *(SilcBool *)val;
245 else if (!strcmp(name, "connections_max")) {
246 config->param.connections_max = (SilcUInt32) *(int *)val;
248 else if (!strcmp(name, "connections_max_per_host")) {
249 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
251 else if (!strcmp(name, "keepalive_secs")) {
252 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
254 else if (!strcmp(name, "reconnect_count")) {
255 config->param.reconnect_count = (SilcUInt32) *(int *)val;
257 else if (!strcmp(name, "reconnect_interval")) {
258 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
260 else if (!strcmp(name, "reconnect_interval_max")) {
261 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
263 else if (!strcmp(name, "reconnect_keep_trying")) {
264 config->param.reconnect_keep_trying = *(SilcBool *)val;
266 else if (!strcmp(name, "key_exchange_rekey")) {
267 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
269 else if (!strcmp(name, "key_exchange_pfs")) {
270 config->param.key_exchange_pfs = *(SilcBool *)val;
272 else if (!strcmp(name, "channel_rekey_secs")) {
273 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
275 else if (!strcmp(name, "key_exchange_timeout")) {
276 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
278 else if (!strcmp(name, "conn_auth_timeout")) {
279 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
281 else if (!strcmp(name, "version_protocol")) {
282 CONFIG_IS_DOUBLE(config->param.version_protocol);
283 config->param.version_protocol =
284 (*(char *)val ? strdup((char *) val) : NULL);
286 else if (!strcmp(name, "version_software")) {
287 CONFIG_IS_DOUBLE(config->param.version_software);
288 config->param.version_software =
289 (*(char *)val ? strdup((char *) val) : NULL);
291 else if (!strcmp(name, "version_software_vendor")) {
292 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
293 config->param.version_software_vendor =
294 (*(char *)val ? strdup((char *) val) : NULL);
296 else if (!strcmp(name, "detach_disabled")) {
297 config->detach_disabled = *(SilcBool *)val;
299 else if (!strcmp(name, "detach_timeout")) {
300 config->detach_timeout = (SilcUInt32) *(int *)val;
302 else if (!strcmp(name, "qos")) {
303 config->param.qos = *(SilcBool *)val;
305 else if (!strcmp(name, "qos_rate_limit")) {
306 config->param.qos_rate_limit = *(SilcUInt32 *)val;
308 else if (!strcmp(name, "qos_bytes_limit")) {
309 config->param.qos_bytes_limit = *(SilcUInt32 *)val;
311 else if (!strcmp(name, "qos_limit_sec")) {
312 config->param.qos_limit_sec = *(SilcUInt32 *)val;
314 else if (!strcmp(name, "qos_limit_usec")) {
315 config->param.qos_limit_usec = *(SilcUInt32 *)val;
317 else if (!strcmp(name, "channel_join_limit")) {
318 config->param.chlimit = *(SilcUInt32 *)val;
320 else if (!strcmp(name, "debug_string")) {
321 CONFIG_IS_DOUBLE(config->debug_string);
322 config->debug_string = (*(char *)val ? strdup((char *) val) : NULL);
325 return SILC_CONFIG_EINTERNAL;
327 return SILC_CONFIG_OK;
333 SILC_CONFIG_CALLBACK(fetch_cipher)
335 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
337 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
338 type, name, context));
339 if (type == SILC_CONFIG_ARG_BLOCK) {
340 /* check the temporary struct's fields */
341 if (!tmp) /* discard empty sub-blocks */
342 return SILC_CONFIG_OK;
344 got_errno = SILC_CONFIG_EMISSFIELDS;
348 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
350 return SILC_CONFIG_OK;
352 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
354 /* Identify and save this value */
355 if (!strcmp(name, "name")) {
356 CONFIG_IS_DOUBLE(tmp->name);
357 tmp->name = strdup((char *) val);
359 else if (!strcmp(name, "module")) {
360 CONFIG_IS_DOUBLE(tmp->module);
361 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
363 else if (!strcmp(name, "keylength")) {
364 tmp->key_length = *(SilcUInt32 *)val;
366 else if (!strcmp(name, "blocklength")) {
367 tmp->block_length = *(SilcUInt32 *)val;
370 return SILC_CONFIG_EINTERNAL;
371 return SILC_CONFIG_OK;
374 silc_free(tmp->name);
375 silc_free(tmp->module);
381 SILC_CONFIG_CALLBACK(fetch_hash)
383 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
385 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
386 type, name, context));
387 if (type == SILC_CONFIG_ARG_BLOCK) {
388 /* check the temporary struct's fields */
389 if (!tmp) /* discard empty sub-blocks */
390 return SILC_CONFIG_OK;
391 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
392 got_errno = SILC_CONFIG_EMISSFIELDS;
396 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
398 return SILC_CONFIG_OK;
400 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
402 /* Identify and save this value */
403 if (!strcmp(name, "name")) {
404 CONFIG_IS_DOUBLE(tmp->name);
405 tmp->name = strdup((char *) val);
407 else if (!strcmp(name, "module")) {
408 CONFIG_IS_DOUBLE(tmp->module);
409 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
411 else if (!strcmp(name, "blocklength")) {
412 tmp->block_length = *(int *)val;
414 else if (!strcmp(name, "digestlength")) {
415 tmp->digest_length = *(int *)val;
418 return SILC_CONFIG_EINTERNAL;
419 return SILC_CONFIG_OK;
422 silc_free(tmp->name);
423 silc_free(tmp->module);
429 SILC_CONFIG_CALLBACK(fetch_hmac)
431 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
433 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
434 type, name, context));
435 if (type == SILC_CONFIG_ARG_BLOCK) {
436 /* check the temporary struct's fields */
437 if (!tmp) /* discard empty sub-blocks */
438 return SILC_CONFIG_OK;
439 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
440 got_errno = SILC_CONFIG_EMISSFIELDS;
444 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
446 return SILC_CONFIG_OK;
448 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
450 /* Identify and save this value */
451 if (!strcmp(name, "name")) {
452 CONFIG_IS_DOUBLE(tmp->name);
453 tmp->name = strdup((char *) val);
455 else if (!strcmp(name, "hash")) {
456 CONFIG_IS_DOUBLE(tmp->hash);
457 tmp->hash = strdup((char *) val);
459 else if (!strcmp(name, "maclength")) {
460 tmp->mac_length = *(int *)val;
463 return SILC_CONFIG_EINTERNAL;
464 return SILC_CONFIG_OK;
467 silc_free(tmp->name);
468 silc_free(tmp->hash);
474 SILC_CONFIG_CALLBACK(fetch_pkcs)
476 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
478 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
479 type, name, context));
480 if (type == SILC_CONFIG_ARG_BLOCK) {
481 /* Check the temporary struct's fields */
482 if (!tmp) /* discard empty sub-blocks */
483 return SILC_CONFIG_OK;
485 got_errno = SILC_CONFIG_EMISSFIELDS;
489 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
491 return SILC_CONFIG_OK;
493 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
495 /* Identify and save this value */
496 if (!strcmp(name, "name")) {
497 CONFIG_IS_DOUBLE(tmp->name);
498 tmp->name = strdup((char *) val);
501 return SILC_CONFIG_EINTERNAL;
502 return SILC_CONFIG_OK;
505 silc_free(tmp->name);
511 SILC_CONFIG_CALLBACK(fetch_serverinfo)
513 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
514 SilcServerConfigServerInfo *server_info = config->server_info;
516 SERVER_CONFIG_DEBUG(("Received SERVERINFO type=%d name=\"%s\" (val=%x)",
517 type, name, context));
519 /* If there isn't the main struct alloc it */
521 config->server_info = server_info = (SilcServerConfigServerInfo *)
522 silc_calloc(1, sizeof(*server_info));
524 if (type == SILC_CONFIG_ARG_BLOCK) {
525 if (!strcmp(name, "primary")) {
526 if (server_info->primary) {
527 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
528 "Double primary specification."));
529 got_errno = SILC_CONFIG_EPRINTLINE;
532 CONFIG_IS_DOUBLE(server_info->primary);
534 /* now check the temporary struct, don't accept empty block and
535 make sure all fields are there */
536 if (!tmp || !tmp->server_ip || !tmp->port) {
537 got_errno = SILC_CONFIG_EMISSFIELDS;
540 server_info->primary = tmp;
542 return SILC_CONFIG_OK;
543 } else if (!strcmp(name, "secondary")) {
545 return SILC_CONFIG_OK;
546 if (!tmp || !tmp->server_ip || !tmp->port) {
547 got_errno = SILC_CONFIG_EMISSFIELDS;
550 SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
552 return SILC_CONFIG_OK;
553 } else if (!server_info->public_key || !server_info->private_key) {
554 got_errno = SILC_CONFIG_EMISSFIELDS;
557 return SILC_CONFIG_OK;
559 if (!strcmp(name, "hostname")) {
560 CONFIG_IS_DOUBLE(server_info->server_name);
561 server_info->server_name = strdup((char *) val);
563 else if (!strcmp(name, "ip")) {
564 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
565 CONFIG_IS_DOUBLE(tmp->server_ip);
566 tmp->server_ip = strdup((char *) val);
568 else if (!strcmp(name, "port")) {
569 int port = *(int *)val;
570 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
571 if ((port <= 0) || (port > 65535)) {
572 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
573 "Invalid port number!"));
574 got_errno = SILC_CONFIG_EPRINTLINE;
577 tmp->port = (SilcUInt16) port;
579 else if (!strcmp(name, "servertype")) {
580 CONFIG_IS_DOUBLE(server_info->server_type);
581 server_info->server_type = strdup((char *) val);
583 else if (!strcmp(name, "admin")) {
584 CONFIG_IS_DOUBLE(server_info->admin);
585 server_info->admin = strdup((char *) val);
587 else if (!strcmp(name, "adminemail")) {
588 CONFIG_IS_DOUBLE(server_info->email);
589 server_info->email = strdup((char *) val);
591 else if (!strcmp(name, "location")) {
592 CONFIG_IS_DOUBLE(server_info->location);
593 server_info->location = strdup((char *) val);
595 else if (!strcmp(name, "user")) {
596 CONFIG_IS_DOUBLE(server_info->user);
597 server_info->user = strdup((char *) val);
599 else if (!strcmp(name, "group")) {
600 CONFIG_IS_DOUBLE(server_info->group);
601 server_info->group = strdup((char *) val);
603 else if (!strcmp(name, "motdfile")) {
604 CONFIG_IS_DOUBLE(server_info->motd_file);
605 server_info->motd_file = strdup((char *) val);
607 else if (!strcmp(name, "pidfile")) {
608 CONFIG_IS_DOUBLE(server_info->pid_file);
609 server_info->pid_file = strdup((char *) val);
611 else if (!strcmp(name, "publickey")) {
612 char *file_tmp = (char *) val;
613 CONFIG_IS_DOUBLE(server_info->public_key);
615 /* Try to load specified file, if fail stop config parsing */
616 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key)) {
617 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
618 return SILC_CONFIG_EPRINTLINE;
621 else if (!strcmp(name, "privatekey")) {
623 char *file_tmp = (char *) val;
624 CONFIG_IS_DOUBLE(server_info->private_key);
626 /* Check the private key file permissions. */
627 if ((stat(file_tmp, &st)) != -1) {
628 if ((st.st_mode & 0777) != 0600) {
629 SILC_SERVER_LOG_ERROR(("Wrong permissions in private key "
630 "file \"%s\". The permissions must be "
632 return SILC_CONFIG_ESILENT;
636 /* Try to load specified file, if fail stop config parsing */
637 if (!silc_pkcs_load_private_key(file_tmp, "", 0,
638 &server_info->private_key)) {
639 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
640 return SILC_CONFIG_EPRINTLINE;
644 return SILC_CONFIG_EINTERNAL;
645 return SILC_CONFIG_OK;
648 /* Here we need to check if tmp exists because this function handles
649 * misc data (multiple fields and single-only fields) */
651 silc_free(tmp->server_ip);
658 SILC_CONFIG_CALLBACK(fetch_logging)
660 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
662 if (!strcmp(name, "timestamp")) {
663 config->logging_timestamp = *(SilcBool *)val;
665 else if (!strcmp(name, "quicklogs")) {
666 config->logging_quick = *(SilcBool *)val;
668 else if (!strcmp(name, "flushdelay")) {
669 int flushdelay = *(int *)val;
670 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
671 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
672 "Invalid flushdelay value, use quicklogs if you "
673 "want real-time logging."));
674 return SILC_CONFIG_EPRINTLINE;
676 config->logging_flushdelay = (long) flushdelay;
679 /* The following istances happens only in Logging's sub-blocks, a match
680 for the sub-block name means that you should store the filename/maxsize
681 temporary struct to the proper logging channel.
682 If we get a match for "file" or "maxsize" this means that we are inside
683 a sub-sub-block and it is safe to alloc a new tmp. */
684 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
685 else if (!strcmp(name, __chan__)) { \
686 if (!tmp) return SILC_CONFIG_OK; \
688 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
690 config->__member__ = tmp; \
691 config->tmp = NULL; \
693 FETCH_LOGGING_CHAN("info", logging_info)
694 FETCH_LOGGING_CHAN("warnings", logging_warnings)
695 FETCH_LOGGING_CHAN("errors", logging_errors)
696 FETCH_LOGGING_CHAN("fatals", logging_fatals)
697 #undef FETCH_LOGGING_CHAN
698 else if (!strcmp(name, "file")) {
699 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
700 CONFIG_IS_DOUBLE(tmp->file);
701 tmp->file = strdup((char *) val);
703 else if (!strcmp(name, "size")) {
705 config->tmp = silc_calloc(1, sizeof(*tmp));
706 tmp = (SilcServerConfigLogging *) config->tmp;
708 tmp->maxsize = *(SilcUInt32 *) val;
711 return SILC_CONFIG_EINTERNAL;
712 return SILC_CONFIG_OK;
715 silc_free(tmp->file);
721 SILC_CONFIG_CALLBACK(fetch_connparam)
723 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
725 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
726 type, name, context));
727 if (type == SILC_CONFIG_ARG_BLOCK) {
728 /* check the temporary struct's fields */
729 if (!tmp) /* discard empty sub-blocks */
730 return SILC_CONFIG_OK;
732 got_errno = SILC_CONFIG_EMISSFIELDS;
736 my_set_param_defaults(tmp, &config->param);
738 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
740 return SILC_CONFIG_OK;
743 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
744 tmp->reconnect_keep_trying = TRUE;
747 if (!strcmp(name, "name")) {
748 CONFIG_IS_DOUBLE(tmp->name);
749 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
751 else if (!strcmp(name, "connections_max")) {
752 tmp->connections_max = *(SilcUInt32 *)val;
754 else if (!strcmp(name, "connections_max_per_host")) {
755 tmp->connections_max_per_host = *(SilcUInt32 *)val;
757 else if (!strcmp(name, "keepalive_secs")) {
758 tmp->keepalive_secs = *(SilcUInt32 *)val;
760 else if (!strcmp(name, "reconnect_count")) {
761 tmp->reconnect_count = *(SilcUInt32 *)val;
763 else if (!strcmp(name, "reconnect_interval")) {
764 tmp->reconnect_interval = *(SilcUInt32 *)val;
766 else if (!strcmp(name, "reconnect_interval_max")) {
767 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
769 else if (!strcmp(name, "reconnect_keep_trying")) {
770 tmp->reconnect_keep_trying = *(SilcBool *)val;
772 else if (!strcmp(name, "key_exchange_rekey")) {
773 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
775 else if (!strcmp(name, "key_exchange_pfs")) {
776 tmp->key_exchange_pfs = *(SilcBool *)val;
778 else if (!strcmp(name, "version_protocol")) {
779 CONFIG_IS_DOUBLE(tmp->version_protocol);
780 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
782 else if (!strcmp(name, "version_software")) {
783 CONFIG_IS_DOUBLE(tmp->version_software);
784 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
786 else if (!strcmp(name, "version_software_vendor")) {
787 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
788 tmp->version_software_vendor =
789 (*(char *)val ? strdup((char *) val) : NULL);
791 else if (!strcmp(name, "anonymous")) {
792 tmp->anonymous = *(SilcBool *)val;
794 else if (!strcmp(name, "qos")) {
795 tmp->qos = *(SilcBool *)val;
797 else if (!strcmp(name, "qos_rate_limit")) {
798 tmp->qos_rate_limit = *(SilcUInt32 *)val;
800 else if (!strcmp(name, "qos_bytes_limit")) {
801 tmp->qos_bytes_limit = *(SilcUInt32 *)val;
803 else if (!strcmp(name, "qos_limit_sec")) {
804 tmp->qos_limit_sec = *(SilcUInt32 *)val;
806 else if (!strcmp(name, "qos_limit_usec")) {
807 tmp->qos_limit_usec = *(SilcUInt32 *)val;
810 return SILC_CONFIG_EINTERNAL;
812 return SILC_CONFIG_OK;
815 silc_free(tmp->name);
821 SILC_CONFIG_CALLBACK(fetch_client)
823 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
825 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
826 type, name, context));
828 /* Alloc before block checking, because empty sub-blocks are welcome here */
829 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
831 if (type == SILC_CONFIG_ARG_BLOCK) {
832 /* empty sub-blocks are welcome */
833 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
835 return SILC_CONFIG_OK;
838 /* Identify and save this value */
839 if (!strcmp(name, "host")) {
840 CONFIG_IS_DOUBLE(tmp->host);
841 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
843 else if (!strcmp(name, "passphrase")) {
844 CONFIG_IS_DOUBLE(tmp->passphrase);
845 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
846 (void *)&tmp->passphrase,
847 &tmp->passphrase_len, 0, NULL)) {
848 got_errno = SILC_CONFIG_EPRINTLINE;
852 else if (!strcmp(name, "publickey")) {
853 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
854 (void *)&config->server->repository, NULL,
855 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
856 got_errno = SILC_CONFIG_EPRINTLINE;
860 else if (!strcmp(name, "publickeydir")) {
861 if (!my_parse_publickeydir((char *) val,
862 (void *)&config->server->repository,
863 SILC_SKR_USAGE_KEY_AGREEMENT)) {
864 got_errno = SILC_CONFIG_EPRINTLINE;
868 else if (!strcmp(name, "params")) {
869 CONFIG_IS_DOUBLE(tmp->param);
870 tmp->param = my_find_param(config, (char *) val);
871 if (!tmp->param) { /* error message already output */
872 got_errno = SILC_CONFIG_EPRINTLINE;
877 return SILC_CONFIG_EINTERNAL;
878 return SILC_CONFIG_OK;
881 silc_free(tmp->host);
882 CONFIG_FREE_AUTH(tmp);
888 SILC_CONFIG_CALLBACK(fetch_admin)
890 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
892 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
893 type, name, context));
894 if (type == SILC_CONFIG_ARG_BLOCK) {
895 /* check the temporary struct's fields */
896 if (!tmp) /* discard empty sub-blocks */
897 return SILC_CONFIG_OK;
899 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
901 return SILC_CONFIG_OK;
903 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
905 /* Identify and save this value */
906 if (!strcmp(name, "host")) {
907 CONFIG_IS_DOUBLE(tmp->host);
908 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
910 else if (!strcmp(name, "user")) {
911 CONFIG_IS_DOUBLE(tmp->user);
912 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
914 else if (!strcmp(name, "nick")) {
915 CONFIG_IS_DOUBLE(tmp->nick);
916 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
918 else if (!strcmp(name, "passphrase")) {
919 CONFIG_IS_DOUBLE(tmp->passphrase);
920 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
921 (void *)&tmp->passphrase,
922 &tmp->passphrase_len, 0, NULL)) {
923 got_errno = SILC_CONFIG_EPRINTLINE;
927 else if (!strcmp(name, "publickey")) {
928 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
929 (void *)&config->server->repository, NULL,
930 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, tmp)) {
931 got_errno = SILC_CONFIG_EPRINTLINE;
936 return SILC_CONFIG_EINTERNAL;
937 return SILC_CONFIG_OK;
940 silc_free(tmp->host);
941 silc_free(tmp->user);
942 silc_free(tmp->nick);
943 CONFIG_FREE_AUTH(tmp);
949 SILC_CONFIG_CALLBACK(fetch_deny)
951 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
953 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
954 type, name, context));
955 if (type == SILC_CONFIG_ARG_BLOCK) {
956 /* check the temporary struct's fields */
957 if (!tmp) /* discard empty sub-blocks */
958 return SILC_CONFIG_OK;
960 got_errno = SILC_CONFIG_EMISSFIELDS;
964 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
966 return SILC_CONFIG_OK;
968 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
970 /* Identify and save this value */
971 if (!strcmp(name, "host")) {
972 CONFIG_IS_DOUBLE(tmp->host);
973 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
975 else if (!strcmp(name, "reason")) {
976 CONFIG_IS_DOUBLE(tmp->reason);
977 tmp->reason = strdup((char *) val);
980 return SILC_CONFIG_EINTERNAL;
981 return SILC_CONFIG_OK;
984 silc_free(tmp->host);
985 silc_free(tmp->reason);
991 SILC_CONFIG_CALLBACK(fetch_server)
993 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
995 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
996 type, name, context));
997 if (type == SILC_CONFIG_ARG_BLOCK) {
998 /* check the temporary struct's fields */
999 if (!tmp) /* discard empty sub-blocks */
1000 return SILC_CONFIG_OK;
1002 got_errno = SILC_CONFIG_EMISSFIELDS;
1006 /* the temporary struct is ok, append it to the list */
1007 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
1009 return SILC_CONFIG_OK;
1011 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
1013 /* Identify and save this value */
1014 if (!strcmp(name, "host")) {
1015 CONFIG_IS_DOUBLE(tmp->host);
1016 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
1018 else if (!strcmp(name, "passphrase")) {
1019 CONFIG_IS_DOUBLE(tmp->passphrase);
1020 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1021 (void *)&tmp->passphrase,
1022 &tmp->passphrase_len, 0, NULL)) {
1023 got_errno = SILC_CONFIG_EPRINTLINE;
1027 else if (!strcmp(name, "publickey")) {
1028 CONFIG_IS_DOUBLE(tmp->publickeys);
1029 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1030 (void *)&config->server->repository, NULL,
1031 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
1032 got_errno = SILC_CONFIG_EPRINTLINE;
1036 else if (!strcmp(name, "params")) {
1037 CONFIG_IS_DOUBLE(tmp->param);
1038 tmp->param = my_find_param(config, (char *) val);
1039 if (!tmp->param) { /* error message already output */
1040 got_errno = SILC_CONFIG_EPRINTLINE;
1044 else if (!strcmp(name, "backup")) {
1045 tmp->backup_router = *(SilcBool *)val;
1048 return SILC_CONFIG_EINTERNAL;
1050 return SILC_CONFIG_OK;
1053 silc_free(tmp->host);
1054 CONFIG_FREE_AUTH(tmp);
1060 SILC_CONFIG_CALLBACK(fetch_router)
1062 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
1064 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
1065 type, name, context));
1066 if (type == SILC_CONFIG_ARG_BLOCK) {
1067 if (!tmp) /* discard empty sub-blocks */
1068 return SILC_CONFIG_OK;
1070 got_errno = SILC_CONFIG_EMISSFIELDS;
1074 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
1076 return SILC_CONFIG_OK;
1078 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
1080 /* Identify and save this value */
1081 if (!strcmp(name, "host")) {
1082 CONFIG_IS_DOUBLE(tmp->host);
1083 tmp->host = strdup((char *) val);
1085 else if (!strcmp(name, "port")) {
1086 int port = *(int *)val;
1087 if ((port <= 0) || (port > 65535)) {
1088 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1089 "Invalid port number!"));
1090 got_errno = SILC_CONFIG_EPRINTLINE;
1093 tmp->port = (SilcUInt16) port;
1095 else if (!strcmp(name, "passphrase")) {
1096 CONFIG_IS_DOUBLE(tmp->passphrase);
1097 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1098 (void *)&tmp->passphrase,
1099 &tmp->passphrase_len, 0, NULL)) {
1100 got_errno = SILC_CONFIG_EPRINTLINE;
1104 else if (!strcmp(name, "publickey")) {
1105 CONFIG_IS_DOUBLE(tmp->publickeys);
1106 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1107 (void *)&config->server->repository, NULL,
1108 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
1109 got_errno = SILC_CONFIG_EPRINTLINE;
1113 else if (!strcmp(name, "params")) {
1114 CONFIG_IS_DOUBLE(tmp->param);
1115 tmp->param = my_find_param(config, (char *) val);
1116 if (!tmp->param) { /* error message already output */
1117 got_errno = SILC_CONFIG_EPRINTLINE;
1121 else if (!strcmp(name, "initiator")) {
1122 tmp->initiator = *(SilcBool *)val;
1124 else if (!strcmp(name, "backuphost")) {
1125 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
1126 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
1128 tmp->backup_router = TRUE;
1130 else if (!strcmp(name, "backupport")) {
1131 int port = *(int *)val;
1132 if ((port <= 0) || (port > 65535)) {
1133 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1134 "Invalid port number!"));
1135 got_errno = SILC_CONFIG_EPRINTLINE;
1138 tmp->backup_replace_port = (SilcUInt16) port;
1140 else if (!strcmp(name, "backuplocal")) {
1141 tmp->backup_local = *(SilcBool *)val;
1144 return SILC_CONFIG_EINTERNAL;
1146 return SILC_CONFIG_OK;
1149 silc_free(tmp->host);
1150 silc_free(tmp->backup_replace_ip);
1151 CONFIG_FREE_AUTH(tmp);
1157 /* known config options tables */
1158 static const SilcConfigTable table_general[] = {
1159 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1160 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1161 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1162 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1163 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1164 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1165 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1166 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1167 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1168 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1169 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1170 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1171 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1172 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1173 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1174 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1175 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1176 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1177 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1178 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1179 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1180 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1181 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1182 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1183 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1184 { "channel_join_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1185 { "debug_string", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1189 static const SilcConfigTable table_cipher[] = {
1190 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1191 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1192 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1193 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1197 static const SilcConfigTable table_hash[] = {
1198 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1199 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1200 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1201 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1205 static const SilcConfigTable table_hmac[] = {
1206 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1207 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1208 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1212 static const SilcConfigTable table_pkcs[] = {
1213 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1217 static const SilcConfigTable table_serverinfo_c[] = {
1218 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1219 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1223 static const SilcConfigTable table_serverinfo[] = {
1224 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1225 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1226 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1227 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1228 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1229 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1230 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1231 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1232 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1233 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1234 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1235 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1236 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1240 static const SilcConfigTable table_logging_c[] = {
1241 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1242 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1243 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1247 static const SilcConfigTable table_logging[] = {
1248 { "timestamp", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1249 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1250 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1251 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1252 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1253 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1254 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1258 static const SilcConfigTable table_connparam[] = {
1259 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1260 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1261 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1262 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1263 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1264 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1265 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1266 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1267 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1268 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1269 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1270 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1271 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1272 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1273 { "anonymous", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1274 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1275 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1276 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1277 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1278 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1282 static const SilcConfigTable table_client[] = {
1283 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1284 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1285 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1286 { "publickeydir", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1287 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1291 static const SilcConfigTable table_admin[] = {
1292 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1293 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1294 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1295 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1296 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1297 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1298 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1302 static const SilcConfigTable table_deny[] = {
1303 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1304 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1308 static const SilcConfigTable table_serverconn[] = {
1309 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1310 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1311 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1312 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1313 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1317 static const SilcConfigTable table_routerconn[] = {
1318 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1319 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1320 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1321 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1322 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1323 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1324 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1325 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1326 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1330 static const SilcConfigTable table_main[] = {
1331 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1332 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1333 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1334 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1335 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1336 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1337 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1338 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1339 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1340 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1341 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1342 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1343 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1347 /* Set default values to stuff that was not configured. */
1349 static void silc_server_config_set_defaults(SilcServerConfig config)
1351 my_set_param_defaults(&config->param, NULL);
1353 config->channel_rekey_secs = (config->channel_rekey_secs ?
1354 config->channel_rekey_secs :
1355 SILC_SERVER_CHANNEL_REKEY);
1356 config->key_exchange_timeout = (config->key_exchange_timeout ?
1357 config->key_exchange_timeout :
1358 SILC_SERVER_SKE_TIMEOUT);
1359 config->conn_auth_timeout = (config->conn_auth_timeout ?
1360 config->conn_auth_timeout :
1361 SILC_SERVER_CONNAUTH_TIMEOUT);
1364 /* Check for correctness of the configuration */
1366 static SilcBool silc_server_config_check(SilcServerConfig config)
1368 SilcBool ret = TRUE;
1369 SilcServerConfigServer *s;
1370 SilcServerConfigRouter *r;
1373 /* ServerConfig is mandatory */
1374 if (!config->server_info) {
1375 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `ServerInfo'"));
1379 /* RouterConnection sanity checks */
1381 if (config->routers && config->routers->backup_router == TRUE &&
1383 SILC_SERVER_LOG_ERROR((
1384 "\nError: First RouterConnection block must be primary router "
1385 "connection. You have marked it incorrectly as backup router."));
1389 if (config->routers && config->routers->initiator == FALSE &&
1390 config->routers->backup_router == FALSE) {
1391 SILC_SERVER_LOG_ERROR((
1392 "\nError: First RouterConnection block must be primary router "
1393 "connection and it must be marked as Initiator."));
1397 if (config->routers && config->routers->backup_router == TRUE &&
1398 !config->servers && !config->routers->next) {
1399 SILC_SERVER_LOG_ERROR((
1400 "\nError: You have configured backup router but not primary router. "
1401 "If backup router is configured also primary router must be "
1406 /* Backup router sanity checks */
1408 for (r = config->routers; r; r = r->next) {
1409 if (r->backup_router && !strcmp(r->host, r->backup_replace_ip)) {
1410 SILC_SERVER_LOG_ERROR((
1411 "\nError: Backup router connection incorrectly configured to use "
1412 "primary and backup router as same host `%s'. They must not be "
1413 "same host.", r->host));
1417 if (r->initiator == FALSE && r->port != 0) {
1418 SILC_SERVER_LOG_WARNING(("\nWarning: Initiator is FALSE and Port is "
1419 "specified. Ignoring Port value."));
1424 /* ServerConnection sanity checks */
1426 for (s = config->servers; s; s = s->next) {
1427 if (s->backup_router) {
1433 for (s = config->servers; s; s = s->next) {
1434 if (!s->backup_router) {
1435 SILC_SERVER_LOG_ERROR((
1436 "\nError: Your server is backup router but not all ServerConnection "
1437 "blocks were marked as backup connections. They all must be "
1438 "marked as backup connections."));
1448 /* Allocates a new configuration object, opens configuration file and
1449 parses it. The parsed data is returned to the newly allocated
1450 configuration object. The SilcServerConfig must be freed by calling
1451 the silc_server_config_destroy function. */
1453 SilcServerConfig silc_server_config_alloc(const char *filename,
1456 SilcServerConfig config_new;
1457 SilcConfigEntity ent;
1458 SilcConfigFile *file;
1460 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1462 /* alloc a config object */
1463 config_new = silc_calloc(1, sizeof(*config_new));
1467 /* general config defaults */
1468 config_new->refcount = 1;
1469 config_new->logging_timestamp = TRUE;
1470 config_new->param.reconnect_keep_trying = TRUE;
1471 config_new->server = server;
1473 /* obtain a config file object */
1474 file = silc_config_open(filename);
1476 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
1481 /* obtain a SilcConfig entity, we can use it to start the parsing */
1482 ent = silc_config_init(file);
1484 /* load the known configuration options, give our empty object as context */
1485 silc_config_register_table(ent, table_main, (void *) config_new);
1487 /* enter the main parsing loop. When this returns, we have the parsing
1488 * result and the object filled (or partially, in case of errors). */
1489 ret = silc_config_main(ent);
1490 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1491 silc_config_strerror(ret)));
1493 /* Check if the parser returned errors */
1495 /* handle this special error return which asks to quietly return */
1496 if (ret != SILC_CONFIG_ESILENT) {
1497 char *linebuf, *filename = silc_config_get_filename(file);
1498 SilcUInt32 line = silc_config_get_line(file);
1499 if (ret != SILC_CONFIG_EPRINTLINE)
1500 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
1501 silc_config_strerror(ret)));
1502 linebuf = silc_config_read_line(file, line);
1504 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1509 silc_server_config_destroy(config_new);
1510 silc_config_close(file);
1514 /* close (destroy) the file object */
1515 silc_config_close(file);
1517 /* Check the configuration */
1518 if (!silc_server_config_check(config_new)) {
1519 silc_server_config_destroy(config_new);
1523 /* Set default to configuration parameters */
1524 silc_server_config_set_defaults(config_new);
1529 /* Increments the reference counter of a config object */
1531 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1536 ref->config = config;
1537 ref->ref_ptr = ref_ptr;
1538 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1539 config->refcount - 1, config->refcount));
1543 /* Decrements the reference counter of a config object. If the counter
1544 reaches 0, the config object is destroyed. */
1546 void silc_server_config_unref(SilcServerConfigRef *ref)
1549 silc_server_config_destroy(ref->config);
1552 /* Destroy a config object with all his children lists */
1554 void silc_server_config_destroy(SilcServerConfig config)
1559 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1560 config->refcount + 1, config->refcount));
1561 if (config->refcount > 0)
1564 SILC_LOG_DEBUG(("Freeing config context"));
1566 /* Destroy general config stuff */
1567 silc_free(config->module_path);
1568 silc_free(config->debug_string);
1569 silc_free(config->param.version_protocol);
1570 silc_free(config->param.version_software);
1571 silc_free(config->param.version_software_vendor);
1573 /* Destroy Logging channels */
1574 if (config->logging_info)
1575 silc_free(config->logging_info->file);
1576 if (config->logging_warnings)
1577 silc_free(config->logging_warnings->file);
1578 if (config->logging_errors)
1579 silc_free(config->logging_errors->file);
1580 if (config->logging_fatals)
1581 silc_free(config->logging_fatals->file);
1582 silc_free(config->logging_info);
1583 silc_free(config->logging_warnings);
1584 silc_free(config->logging_errors);
1585 silc_free(config->logging_fatals);
1587 /* Destroy the ServerInfo struct */
1588 if (config->server_info) {
1589 register SilcServerConfigServerInfo *si = config->server_info;
1590 silc_free(si->server_name);
1592 silc_free(si->primary->server_ip);
1593 silc_free(si->primary);
1595 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1597 silc_free(di->server_ip);
1600 silc_free(si->server_type);
1601 silc_free(si->location);
1602 silc_free(si->admin);
1603 silc_free(si->email);
1604 silc_free(si->user);
1605 silc_free(si->group);
1606 silc_free(si->motd_file);
1607 silc_free(si->pid_file);
1608 silc_pkcs_public_key_free(si->public_key);
1609 silc_pkcs_private_key_free(si->private_key);
1613 /* Now let's destroy the lists */
1615 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1617 silc_free(di->name);
1618 silc_free(di->module);
1621 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1622 silc_free(di->name);
1623 silc_free(di->module);
1626 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1627 silc_free(di->name);
1628 silc_free(di->hash);
1631 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1632 silc_free(di->name);
1635 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1636 config->conn_params)
1637 silc_free(di->name);
1638 silc_free(di->version_protocol);
1639 silc_free(di->version_software);
1640 silc_free(di->version_software_vendor);
1643 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1644 silc_free(di->host);
1645 CONFIG_FREE_AUTH(di);
1648 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1649 silc_free(di->host);
1650 silc_free(di->user);
1651 silc_free(di->nick);
1652 CONFIG_FREE_AUTH(di);
1655 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1656 silc_free(di->host);
1657 silc_free(di->reason);
1660 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1662 silc_free(di->host);
1663 CONFIG_FREE_AUTH(di);
1666 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1668 silc_free(di->host);
1669 silc_free(di->backup_replace_ip);
1670 CONFIG_FREE_AUTH(di);
1674 memset(config, 'F', sizeof(*config));
1678 /* Registers configured ciphers. These can then be allocated by the
1679 server when needed. */
1681 SilcBool silc_server_config_register_ciphers(SilcServer server)
1683 SilcServerConfig config = server->config;
1684 SilcServerConfigCipher *cipher = config->cipher;
1685 char *module_path = config->module_path;
1687 SILC_LOG_DEBUG(("Registering configured ciphers"));
1689 if (!cipher) /* any cipher in the config file? */
1693 /* if there isn't a module_path OR there isn't a module sim name try to
1694 * use buil-in functions */
1695 if (!module_path || !cipher->module) {
1697 for (i = 0; silc_default_ciphers[i].name; i++)
1698 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1699 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1702 if (!silc_cipher_is_supported(cipher->name)) {
1703 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1704 silc_server_stop(server);
1708 cipher = cipher->next;
1714 /* Registers configured hash functions. These can then be allocated by the
1715 server when needed. */
1717 SilcBool silc_server_config_register_hashfuncs(SilcServer server)
1719 SilcServerConfig config = server->config;
1720 SilcServerConfigHash *hash = config->hash;
1721 char *module_path = config->module_path;
1723 SILC_LOG_DEBUG(("Registering configured hash functions"));
1725 if (!hash) /* any hash func in the config file? */
1729 /* if there isn't a module_path OR there isn't a module sim name try to
1730 * use buil-in functions */
1731 if (!module_path || !hash->module) {
1733 for (i = 0; silc_default_hash[i].name; i++)
1734 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1735 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1738 if (!silc_hash_is_supported(hash->name)) {
1739 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1740 silc_server_stop(server);
1750 /* Registers configure HMACs. These can then be allocated by the server
1753 SilcBool silc_server_config_register_hmacs(SilcServer server)
1755 SilcServerConfig config = server->config;
1756 SilcServerConfigHmac *hmac = config->hmac;
1758 SILC_LOG_DEBUG(("Registering configured HMACs"));
1764 SilcHmacObject hmac_obj;
1765 if (!silc_hash_is_supported(hmac->hash)) {
1766 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1767 silc_server_stop(server);
1771 /* Register the HMAC */
1772 memset(&hmac_obj, 0, sizeof(hmac_obj));
1773 hmac_obj.name = hmac->name;
1774 hmac_obj.len = hmac->mac_length;
1775 silc_hmac_register(&hmac_obj);
1783 /* Registers configured PKCS's. */
1785 SilcBool silc_server_config_register_pkcs(SilcServer server)
1790 /* Sets log files where log messages are saved by the server logger. */
1792 void silc_server_config_setlogfiles(SilcServer server)
1794 SilcServerConfig config = server->config;
1795 SilcServerConfigLogging *this;
1797 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1799 silc_log_timestamp(config->logging_timestamp);
1800 silc_log_quick(config->logging_quick);
1801 silc_log_flushdelay(config->logging_flushdelay ?
1802 config->logging_flushdelay :
1803 SILC_SERVER_LOG_FLUSH_DELAY);
1805 if ((this = config->logging_fatals))
1806 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1808 if ((this = config->logging_errors))
1809 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1811 if ((this = config->logging_warnings))
1812 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1814 if ((this = config->logging_info))
1815 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1819 /* Returns client authentication information from configuration file by host
1822 SilcServerConfigClient *
1823 silc_server_config_find_client(SilcServer server, char *host)
1825 SilcServerConfig config = server->config;
1826 SilcServerConfigClient *client;
1828 if (!config || !host)
1831 for (client = config->clients; client; client = client->next) {
1832 if (client->host && !silc_string_compare(client->host, host))
1837 /* if none matched, then client is already NULL */
1841 /* Returns admin connection configuration by host, username and/or
1844 SilcServerConfigAdmin *
1845 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1848 SilcServerConfig config = server->config;
1849 SilcServerConfigAdmin *admin;
1851 /* make sure we have a value for the matching parameters */
1859 for (admin = config->admins; admin; admin = admin->next) {
1860 if (admin->host && !silc_string_compare(admin->host, host))
1862 if (admin->user && !silc_string_compare(admin->user, user))
1864 if (admin->nick && !silc_string_compare(admin->nick, nick))
1866 /* no checks failed -> this entry matches */
1870 /* if none matched, then admin is already NULL */
1874 /* Returns the denied connection configuration entry by host. */
1876 SilcServerConfigDeny *
1877 silc_server_config_find_denied(SilcServer server, char *host)
1879 SilcServerConfig config = server->config;
1880 SilcServerConfigDeny *deny;
1882 /* make sure we have a value for the matching parameters */
1883 if (!config || !host)
1886 for (deny = config->denied; deny; deny = deny->next) {
1887 if (deny->host && !silc_string_compare(deny->host, host))
1892 /* if none matched, then deny is already NULL */
1896 /* Returns server connection info from server configuartion by host
1899 SilcServerConfigServer *
1900 silc_server_config_find_server_conn(SilcServer server, char *host)
1902 SilcServerConfig config = server->config;
1903 SilcServerConfigServer *serv = NULL;
1908 if (!config->servers)
1911 for (serv = config->servers; serv; serv = serv->next) {
1912 if (!silc_string_compare(serv->host, host))
1920 /* Returns router connection info from server configuration by
1921 host (name or ip). */
1923 SilcServerConfigRouter *
1924 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1926 SilcServerConfig config = server->config;
1927 SilcServerConfigRouter *serv = NULL;
1932 if (!config->routers)
1935 for (serv = config->routers; serv; serv = serv->next) {
1936 if (!silc_string_compare(serv->host, host))
1938 if (port && serv->port && serv->port != port)
1946 /* Find backup router connection by host (name or ip) */
1948 SilcServerConfigRouter *
1949 silc_server_config_find_backup_conn(SilcServer server, char *host)
1951 SilcServerConfig config = server->config;
1952 SilcServerConfigRouter *serv = NULL;
1957 if (!config->routers)
1960 for (serv = config->routers; serv; serv = serv->next) {
1961 if (!serv->backup_router)
1963 if (!silc_string_compare(serv->host, host))
1971 /* Returns TRUE if configuration for a router connection that we are
1972 initiating exists. */
1974 SilcBool silc_server_config_is_primary_route(SilcServer server)
1976 SilcServerConfig config = server->config;
1977 SilcServerConfigRouter *serv = NULL;
1979 SilcBool found = FALSE;
1981 serv = config->routers;
1982 for (i = 0; serv; i++) {
1983 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1994 /* Returns our primary connection configuration or NULL if we do not
1995 have primary router configured. */
1997 SilcServerConfigRouter *
1998 silc_server_config_get_primary_router(SilcServer server)
2000 SilcServerConfig config = server->config;
2001 SilcServerConfigRouter *serv = NULL;
2004 serv = config->routers;
2005 for (i = 0; serv; i++) {
2006 if (serv->initiator == TRUE && serv->backup_router == FALSE)
2014 /* If we have backup router configured that is going to replace us this
2015 function returns it. */
2017 SilcServerConfigRouter *
2018 silc_server_config_get_backup_router(SilcServer server)
2020 SilcServerConfig config = server->config;
2021 SilcServerConfigRouter *serv = NULL;
2024 if (server->server_type != SILC_ROUTER)
2027 serv = config->routers;
2028 for (i = 0; serv; i++) {
2029 if (serv->initiator == FALSE && serv->backup_router == TRUE &&
2030 serv->backup_local == TRUE &&
2031 !strcmp(server->config->server_info->primary->server_ip,
2032 serv->backup_replace_ip) &&
2033 server->config->server_info->primary->port ==
2034 serv->backup_replace_port)