5 Author: Johnny Mnemonic <johnny@themnemonic.org>
7 Copyright (C) 1997 - 2002 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; either version 2 of the License, or
12 (at your option) any later version.
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.
22 #include "serverincludes.h"
23 #include "server_internal.h"
27 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
29 #define SERVER_CONFIG_DEBUG(fmt)
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; \
38 /* allocate the tmp field for fetching data */
39 #define SILC_SERVER_CONFIG_ALLOCTMP(__type__) \
41 config->tmp = silc_calloc(1, sizeof(*findtmp)); \
42 tmp = (__type__ *) config->tmp; \
45 /* append the tmp field to the specified list */
46 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \
50 for (findtmp = __list__; findtmp->next; findtmp = findtmp->next); \
51 findtmp->next = tmp; \
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;
61 /* Set EDOUBLE error value and bail out if necessary */
62 #define CONFIG_IS_DOUBLE(__x__) \
64 got_errno = SILC_CONFIG_EDOUBLE; \
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);
75 static void my_free_public_key(void *key, void *context, void *user_data)
77 silc_pkcs_public_key_free(context);
80 /* Set default values to those parameters that have not been defined */
82 my_set_param_defaults(SilcServerConfigConnParams *params,
83 SilcServerConfigConnParams *defaults)
85 #define SET_PARAM_DEFAULT(p, d) params->p = \
86 (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
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);
101 #undef SET_PARAM_DEFAULT
104 /* Find connection parameters by the parameter block name. */
105 static SilcServerConfigConnParams *
106 my_find_param(SilcServerConfig config, const char *name)
108 SilcServerConfigConnParams *param;
110 for (param = config->conn_params; param; param = param->next) {
111 if (!strcasecmp(param->name, name))
115 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
116 "Cannot find Params \"%s\".", name));
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)
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,
135 *auth_data = (void *) strdup(p);
136 *auth_data_len = (SilcUInt32) strlen(p);
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;
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!"));
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 */
161 /* The auth_data is a pointer to the hash table of public keys. */
163 if (*auth_data == NULL)
164 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
166 my_free_public_key, NULL,
168 silc_hash_table_add(*auth_data, public_key, public_key);
176 static bool my_parse_publickeydir(const char *dirname, void **auth_data)
179 struct dirent *get_file;
182 if (!(dp = opendir(dirname))) {
183 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
184 "Could not open directory \"%s\"", dirname));
188 /* errors are not considered fatal */
189 while ((get_file = readdir(dp))) {
190 int dirname_len = strlen(dirname);
192 const char *filename = get_file->d_name;
193 struct stat check_file;
195 if (!strcmp(filename, ".") || !strcmp(filename, ".."))
198 snprintf(buf, sizeof(buf) - 2, "%s%s%s", dirname,
199 (dirname[dirname_len - 1] == '/' ? "" : "/"), filename);
200 buf[sizeof(buf) - 1] = 0;
202 if (stat(buf, &check_file) < 0) {
203 SILC_SERVER_LOG_ERROR(("Error stating file %s: %s", buf,
206 else if (S_ISREG(check_file.st_mode)) {
207 my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL);
212 SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname));
218 SILC_CONFIG_CALLBACK(fetch_generic)
220 SilcServerConfig config = (SilcServerConfig) context;
223 if (!strcmp(name, "module_path")) {
224 CONFIG_IS_DOUBLE(config->module_path);
225 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
227 else if (!strcmp(name, "prefer_passphrase_auth")) {
228 config->prefer_passphrase_auth = *(bool *)val;
230 else if (!strcmp(name, "require_reverse_lookup")) {
231 config->require_reverse_lookup = *(bool *)val;
233 else if (!strcmp(name, "connections_max")) {
234 config->param.connections_max = (SilcUInt32) *(int *)val;
236 else if (!strcmp(name, "connections_max_per_host")) {
237 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
239 else if (!strcmp(name, "keepalive_secs")) {
240 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
242 else if (!strcmp(name, "reconnect_count")) {
243 config->param.reconnect_count = (SilcUInt32) *(int *)val;
245 else if (!strcmp(name, "reconnect_interval")) {
246 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
248 else if (!strcmp(name, "reconnect_interval_max")) {
249 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
251 else if (!strcmp(name, "reconnect_keep_trying")) {
252 config->param.reconnect_keep_trying = *(bool *)val;
254 else if (!strcmp(name, "key_exchange_rekey")) {
255 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
257 else if (!strcmp(name, "key_exchange_pfs")) {
258 config->param.key_exchange_pfs = *(bool *)val;
260 else if (!strcmp(name, "channel_rekey_secs")) {
261 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
263 else if (!strcmp(name, "key_exchange_timeout")) {
264 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
266 else if (!strcmp(name, "conn_auth_timeout")) {
267 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
269 else if (!strcmp(name, "version_protocol")) {
270 CONFIG_IS_DOUBLE(config->param.version_protocol);
271 config->param.version_protocol =
272 (*(char *)val ? strdup((char *) val) : NULL);
274 else if (!strcmp(name, "version_software")) {
275 CONFIG_IS_DOUBLE(config->param.version_software);
276 config->param.version_software =
277 (*(char *)val ? strdup((char *) val) : NULL);
279 else if (!strcmp(name, "version_software_vendor")) {
280 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
281 config->param.version_software_vendor =
282 (*(char *)val ? strdup((char *) val) : NULL);
284 else if (!strcmp(name, "detach_disabled")) {
285 config->detach_disabled = *(bool *)val;
287 else if (!strcmp(name, "detach_timeout")) {
288 config->detach_timeout = (SilcUInt32) *(int *)val;
290 else if (!strcmp(name, "qos")) {
291 config->param.qos = *(bool *)val;
293 else if (!strcmp(name, "qos_rate_limit")) {
294 config->param.qos_rate_limit = *(SilcUInt32 *)val;
296 else if (!strcmp(name, "qos_bytes_limit")) {
297 config->param.qos_bytes_limit = *(SilcUInt32 *)val;
299 else if (!strcmp(name, "qos_limit_sec")) {
300 config->param.qos_limit_sec = *(SilcUInt32 *)val;
302 else if (!strcmp(name, "qos_limit_usec")) {
303 config->param.qos_limit_usec = *(SilcUInt32 *)val;
306 return SILC_CONFIG_EINTERNAL;
308 return SILC_CONFIG_OK;
314 SILC_CONFIG_CALLBACK(fetch_cipher)
316 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
318 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
319 type, name, context));
320 if (type == SILC_CONFIG_ARG_BLOCK) {
321 /* check the temporary struct's fields */
322 if (!tmp) /* discard empty sub-blocks */
323 return SILC_CONFIG_OK;
325 got_errno = SILC_CONFIG_EMISSFIELDS;
329 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
331 return SILC_CONFIG_OK;
333 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
335 /* Identify and save this value */
336 if (!strcmp(name, "name")) {
337 CONFIG_IS_DOUBLE(tmp->name);
338 tmp->name = strdup((char *) val);
340 else if (!strcmp(name, "module")) {
341 CONFIG_IS_DOUBLE(tmp->module);
342 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
344 else if (!strcmp(name, "keylength")) {
345 tmp->key_length = *(SilcUInt32 *)val;
347 else if (!strcmp(name, "blocklength")) {
348 tmp->block_length = *(SilcUInt32 *)val;
351 return SILC_CONFIG_EINTERNAL;
352 return SILC_CONFIG_OK;
355 silc_free(tmp->name);
356 silc_free(tmp->module);
362 SILC_CONFIG_CALLBACK(fetch_hash)
364 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
366 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
367 type, name, context));
368 if (type == SILC_CONFIG_ARG_BLOCK) {
369 /* check the temporary struct's fields */
370 if (!tmp) /* discard empty sub-blocks */
371 return SILC_CONFIG_OK;
372 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
373 got_errno = SILC_CONFIG_EMISSFIELDS;
377 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
379 return SILC_CONFIG_OK;
381 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
383 /* Identify and save this value */
384 if (!strcmp(name, "name")) {
385 CONFIG_IS_DOUBLE(tmp->name);
386 tmp->name = strdup((char *) val);
388 else if (!strcmp(name, "module")) {
389 CONFIG_IS_DOUBLE(tmp->module);
390 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
392 else if (!strcmp(name, "blocklength")) {
393 tmp->block_length = *(int *)val;
395 else if (!strcmp(name, "digestlength")) {
396 tmp->digest_length = *(int *)val;
399 return SILC_CONFIG_EINTERNAL;
400 return SILC_CONFIG_OK;
403 silc_free(tmp->name);
404 silc_free(tmp->module);
410 SILC_CONFIG_CALLBACK(fetch_hmac)
412 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
414 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
415 type, name, context));
416 if (type == SILC_CONFIG_ARG_BLOCK) {
417 /* check the temporary struct's fields */
418 if (!tmp) /* discard empty sub-blocks */
419 return SILC_CONFIG_OK;
420 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
421 got_errno = SILC_CONFIG_EMISSFIELDS;
425 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
427 return SILC_CONFIG_OK;
429 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
431 /* Identify and save this value */
432 if (!strcmp(name, "name")) {
433 CONFIG_IS_DOUBLE(tmp->name);
434 tmp->name = strdup((char *) val);
436 else if (!strcmp(name, "hash")) {
437 CONFIG_IS_DOUBLE(tmp->hash);
438 tmp->hash = strdup((char *) val);
440 else if (!strcmp(name, "maclength")) {
441 tmp->mac_length = *(int *)val;
444 return SILC_CONFIG_EINTERNAL;
445 return SILC_CONFIG_OK;
448 silc_free(tmp->name);
449 silc_free(tmp->hash);
455 SILC_CONFIG_CALLBACK(fetch_pkcs)
457 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
459 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
460 type, name, context));
461 if (type == SILC_CONFIG_ARG_BLOCK) {
462 /* check the temporary struct's fields */
463 if (!tmp) /* discard empty sub-blocks */
464 return SILC_CONFIG_OK;
466 got_errno = SILC_CONFIG_EMISSFIELDS;
470 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
472 return SILC_CONFIG_OK;
474 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
476 /* Identify and save this value */
477 if (!strcmp(name, "name")) {
478 CONFIG_IS_DOUBLE(tmp->name);
479 tmp->name = strdup((char *) val);
482 return SILC_CONFIG_EINTERNAL;
483 return SILC_CONFIG_OK;
486 silc_free(tmp->name);
492 SILC_CONFIG_CALLBACK(fetch_serverinfo)
494 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
495 SilcServerConfigServerInfo *server_info = config->server_info;
497 /* if there isn't the struct alloc it */
499 config->server_info = server_info = (SilcServerConfigServerInfo *)
500 silc_calloc(1, sizeof(*server_info));
502 if (type == SILC_CONFIG_ARG_BLOCK) {
503 if (!strcmp(name, "primary")) {
504 CONFIG_IS_DOUBLE(server_info->primary);
506 return SILC_CONFIG_OK;
507 server_info->primary = tmp;
509 return SILC_CONFIG_OK;
510 } else if (!strcmp(name, "secondary")) {
512 return SILC_CONFIG_OK;
513 SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
515 return SILC_CONFIG_OK;
516 } else if (!server_info->public_key || !server_info->private_key) {
517 got_errno = SILC_CONFIG_EMISSFIELDS;
520 return SILC_CONFIG_OK;
522 if (!strcmp(name, "hostname")) {
523 CONFIG_IS_DOUBLE(server_info->server_name);
524 server_info->server_name = strdup((char *) val);
526 else if (!strcmp(name, "ip")) {
527 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
528 CONFIG_IS_DOUBLE(tmp->server_ip);
529 tmp->server_ip = strdup((char *) val);
531 else if (!strcmp(name, "port")) {
532 int port = *(int *)val;
533 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
534 if ((port <= 0) || (port > 65535)) {
535 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
536 "Invalid port number!"));
537 got_errno = SILC_CONFIG_EPRINTLINE;
540 tmp->port = (SilcUInt16) port;
542 else if (!strcmp(name, "servertype")) {
543 CONFIG_IS_DOUBLE(server_info->server_type);
544 server_info->server_type = strdup((char *) val);
546 else if (!strcmp(name, "admin")) {
547 CONFIG_IS_DOUBLE(server_info->admin);
548 server_info->admin = strdup((char *) val);
550 else if (!strcmp(name, "adminemail")) {
551 CONFIG_IS_DOUBLE(server_info->email);
552 server_info->email = strdup((char *) val);
554 else if (!strcmp(name, "location")) {
555 CONFIG_IS_DOUBLE(server_info->location);
556 server_info->location = strdup((char *) val);
558 else if (!strcmp(name, "user")) {
559 CONFIG_IS_DOUBLE(server_info->user);
560 server_info->user = strdup((char *) val);
562 else if (!strcmp(name, "group")) {
563 CONFIG_IS_DOUBLE(server_info->group);
564 server_info->group = strdup((char *) val);
566 else if (!strcmp(name, "motdfile")) {
567 CONFIG_IS_DOUBLE(server_info->motd_file);
568 server_info->motd_file = strdup((char *) val);
570 else if (!strcmp(name, "pidfile")) {
571 CONFIG_IS_DOUBLE(server_info->pid_file);
572 server_info->pid_file = strdup((char *) val);
574 else if (!strcmp(name, "publickey")) {
575 char *file_tmp = (char *) val;
576 CONFIG_IS_DOUBLE(server_info->public_key);
578 /* try to load specified file, if fail stop config parsing */
579 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
581 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
582 SILC_PKCS_FILE_BIN)) {
583 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
584 return SILC_CONFIG_EPRINTLINE;
587 else if (!strcmp(name, "privatekey")) {
588 char *file_tmp = (char *) val;
589 CONFIG_IS_DOUBLE(server_info->private_key);
591 /* try to load specified file, if fail stop config parsing */
592 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
593 "", 0, SILC_PKCS_FILE_BIN))
594 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
595 "", 0, SILC_PKCS_FILE_PEM)) {
596 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
597 return SILC_CONFIG_EPRINTLINE;
601 return SILC_CONFIG_EINTERNAL;
602 return SILC_CONFIG_OK;
606 silc_free(config->tmp);
611 SILC_CONFIG_CALLBACK(fetch_logging)
613 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
615 if (!strcmp(name, "timestamp")) {
616 config->logging_timestamp = *(bool *)val;
618 else if (!strcmp(name, "quicklogs")) {
619 config->logging_quick = *(bool *)val;
621 else if (!strcmp(name, "flushdelay")) {
622 int flushdelay = *(int *)val;
623 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
624 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
625 "Invalid flushdelay value, use quicklogs if you "
626 "want real-time logging."));
627 return SILC_CONFIG_EPRINTLINE;
629 config->logging_flushdelay = (long) flushdelay;
632 /* The following istances happens only in Logging's sub-blocks, a match
633 for the sub-block name means that you should store the filename/maxsize
634 temporary struct to the proper logging channel.
635 If we get a match for "file" or "maxsize" this means that we are inside
636 a sub-sub-block and it is safe to alloc a new tmp. */
637 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
638 else if (!strcmp(name, __chan__)) { \
639 if (!tmp) return SILC_CONFIG_OK; \
641 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
643 config->__member__ = tmp; \
644 config->tmp = NULL; \
646 FETCH_LOGGING_CHAN("info", logging_info)
647 FETCH_LOGGING_CHAN("warnings", logging_warnings)
648 FETCH_LOGGING_CHAN("errors", logging_errors)
649 FETCH_LOGGING_CHAN("fatals", logging_fatals)
650 #undef FETCH_LOGGING_CHAN
651 else if (!strcmp(name, "file")) {
652 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
653 CONFIG_IS_DOUBLE(tmp->file);
654 tmp->file = strdup((char *) val);
656 else if (!strcmp(name, "size")) {
658 config->tmp = silc_calloc(1, sizeof(*tmp));
659 tmp = (SilcServerConfigLogging *) config->tmp;
661 tmp->maxsize = *(SilcUInt32 *) val;
664 return SILC_CONFIG_EINTERNAL;
665 return SILC_CONFIG_OK;
668 silc_free(tmp->file);
674 SILC_CONFIG_CALLBACK(fetch_connparam)
676 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
678 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
679 type, name, context));
680 if (type == SILC_CONFIG_ARG_BLOCK) {
681 /* check the temporary struct's fields */
682 if (!tmp) /* discard empty sub-blocks */
683 return SILC_CONFIG_OK;
685 got_errno = SILC_CONFIG_EMISSFIELDS;
689 my_set_param_defaults(tmp, &config->param);
691 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
693 return SILC_CONFIG_OK;
695 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
697 if (!strcmp(name, "name")) {
698 CONFIG_IS_DOUBLE(tmp->name);
699 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
701 else if (!strcmp(name, "connections_max")) {
702 tmp->connections_max = *(SilcUInt32 *)val;
704 else if (!strcmp(name, "connections_max_per_host")) {
705 tmp->connections_max_per_host = *(SilcUInt32 *)val;
707 else if (!strcmp(name, "keepalive_secs")) {
708 tmp->keepalive_secs = *(SilcUInt32 *)val;
710 else if (!strcmp(name, "reconnect_count")) {
711 tmp->reconnect_count = *(SilcUInt32 *)val;
713 else if (!strcmp(name, "reconnect_interval")) {
714 tmp->reconnect_interval = *(SilcUInt32 *)val;
716 else if (!strcmp(name, "reconnect_interval_max")) {
717 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
719 else if (!strcmp(name, "reconnect_keep_trying")) {
720 tmp->reconnect_keep_trying = *(bool *)val;
722 else if (!strcmp(name, "key_exchange_rekey")) {
723 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
725 else if (!strcmp(name, "key_exchange_pfs")) {
726 tmp->key_exchange_pfs = *(bool *)val;
728 else if (!strcmp(name, "version_protocol")) {
729 CONFIG_IS_DOUBLE(tmp->version_protocol);
730 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
732 else if (!strcmp(name, "version_software")) {
733 CONFIG_IS_DOUBLE(tmp->version_software);
734 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
736 else if (!strcmp(name, "version_software_vendor")) {
737 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
738 tmp->version_software_vendor =
739 (*(char *)val ? strdup((char *) val) : NULL);
741 else if (!strcmp(name, "anonymous")) {
742 tmp->anonymous = *(bool *)val;
744 else if (!strcmp(name, "qos")) {
745 tmp->qos = *(bool *)val;
747 else if (!strcmp(name, "qos_rate_limit")) {
748 tmp->qos_rate_limit = *(SilcUInt32 *)val;
750 else if (!strcmp(name, "qos_bytes_limit")) {
751 tmp->qos_bytes_limit = *(SilcUInt32 *)val;
753 else if (!strcmp(name, "qos_limit_sec")) {
754 tmp->qos_limit_sec = *(SilcUInt32 *)val;
756 else if (!strcmp(name, "qos_limit_usec")) {
757 tmp->qos_limit_usec = *(SilcUInt32 *)val;
760 return SILC_CONFIG_EINTERNAL;
762 return SILC_CONFIG_OK;
765 silc_free(tmp->name);
771 SILC_CONFIG_CALLBACK(fetch_client)
773 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
775 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
776 type, name, context));
778 /* Alloc before block checking, because empty sub-blocks are welcome here */
779 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
781 if (type == SILC_CONFIG_ARG_BLOCK) {
782 /* empty sub-blocks are welcome */
783 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
785 return SILC_CONFIG_OK;
788 /* Identify and save this value */
789 if (!strcmp(name, "host")) {
790 CONFIG_IS_DOUBLE(tmp->host);
791 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
793 else if (!strcmp(name, "passphrase")) {
794 CONFIG_IS_DOUBLE(tmp->passphrase);
795 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
796 (void **)&tmp->passphrase,
797 &tmp->passphrase_len)) {
798 got_errno = SILC_CONFIG_EPRINTLINE;
802 else if (!strcmp(name, "publickey")) {
803 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
804 (void **)&tmp->publickeys, NULL)) {
805 got_errno = SILC_CONFIG_EPRINTLINE;
809 else if (!strcmp(name, "publickeydir")) {
810 if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) {
811 got_errno = SILC_CONFIG_EPRINTLINE;
815 else if (!strcmp(name, "params")) {
816 CONFIG_IS_DOUBLE(tmp->param);
817 tmp->param = my_find_param(config, (char *) val);
818 if (!tmp->param) { /* error message already output */
819 got_errno = SILC_CONFIG_EPRINTLINE;
824 return SILC_CONFIG_EINTERNAL;
825 return SILC_CONFIG_OK;
828 silc_free(tmp->host);
829 CONFIG_FREE_AUTH(tmp);
835 SILC_CONFIG_CALLBACK(fetch_admin)
837 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
839 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
840 type, name, context));
841 if (type == SILC_CONFIG_ARG_BLOCK) {
842 /* check the temporary struct's fields */
843 if (!tmp) /* discard empty sub-blocks */
844 return SILC_CONFIG_OK;
846 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
848 return SILC_CONFIG_OK;
850 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
852 /* Identify and save this value */
853 if (!strcmp(name, "host")) {
854 CONFIG_IS_DOUBLE(tmp->host);
855 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
857 else if (!strcmp(name, "user")) {
858 CONFIG_IS_DOUBLE(tmp->user);
859 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
861 else if (!strcmp(name, "nick")) {
862 CONFIG_IS_DOUBLE(tmp->nick);
863 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
865 else if (!strcmp(name, "passphrase")) {
866 CONFIG_IS_DOUBLE(tmp->passphrase);
867 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
868 (void **)&tmp->passphrase,
869 &tmp->passphrase_len)) {
870 got_errno = SILC_CONFIG_EPRINTLINE;
874 else if (!strcmp(name, "publickey")) {
875 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
876 (void **)&tmp->publickeys, NULL)) {
877 got_errno = SILC_CONFIG_EPRINTLINE;
881 else if (!strcmp(name, "publickeydir")) {
882 if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) {
883 got_errno = SILC_CONFIG_EPRINTLINE;
888 return SILC_CONFIG_EINTERNAL;
889 return SILC_CONFIG_OK;
892 silc_free(tmp->host);
893 silc_free(tmp->user);
894 silc_free(tmp->nick);
895 CONFIG_FREE_AUTH(tmp);
901 SILC_CONFIG_CALLBACK(fetch_deny)
903 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
905 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
906 type, name, context));
907 if (type == SILC_CONFIG_ARG_BLOCK) {
908 /* check the temporary struct's fields */
909 if (!tmp) /* discard empty sub-blocks */
910 return SILC_CONFIG_OK;
912 got_errno = SILC_CONFIG_EMISSFIELDS;
916 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
918 return SILC_CONFIG_OK;
920 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
922 /* Identify and save this value */
923 if (!strcmp(name, "host")) {
924 CONFIG_IS_DOUBLE(tmp->host);
925 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
927 else if (!strcmp(name, "reason")) {
928 CONFIG_IS_DOUBLE(tmp->reason);
929 tmp->reason = strdup((char *) val);
932 return SILC_CONFIG_EINTERNAL;
933 return SILC_CONFIG_OK;
936 silc_free(tmp->host);
937 silc_free(tmp->reason);
943 SILC_CONFIG_CALLBACK(fetch_server)
945 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
947 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
948 type, name, context));
949 if (type == SILC_CONFIG_ARG_BLOCK) {
950 /* check the temporary struct's fields */
951 if (!tmp) /* discard empty sub-blocks */
952 return SILC_CONFIG_OK;
954 /* the temporary struct is ok, append it to the list */
955 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
957 return SILC_CONFIG_OK;
959 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
961 /* Identify and save this value */
962 if (!strcmp(name, "host")) {
963 CONFIG_IS_DOUBLE(tmp->host);
964 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
966 else if (!strcmp(name, "passphrase")) {
967 CONFIG_IS_DOUBLE(tmp->passphrase);
968 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
969 (void **)&tmp->passphrase,
970 &tmp->passphrase_len)) {
971 got_errno = SILC_CONFIG_EPRINTLINE;
975 else if (!strcmp(name, "publickey")) {
976 CONFIG_IS_DOUBLE(tmp->publickeys);
977 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
978 (void **)&tmp->publickeys, NULL)) {
979 got_errno = SILC_CONFIG_EPRINTLINE;
983 else if (!strcmp(name, "params")) {
984 CONFIG_IS_DOUBLE(tmp->param);
985 tmp->param = my_find_param(config, (char *) val);
986 if (!tmp->param) { /* error message already output */
987 got_errno = SILC_CONFIG_EPRINTLINE;
991 else if (!strcmp(name, "backup")) {
992 tmp->backup_router = *(bool *)val;
995 return SILC_CONFIG_EINTERNAL;
997 return SILC_CONFIG_OK;
1000 silc_free(tmp->host);
1001 CONFIG_FREE_AUTH(tmp);
1007 SILC_CONFIG_CALLBACK(fetch_router)
1009 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
1011 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
1012 type, name, context));
1013 if (type == SILC_CONFIG_ARG_BLOCK) {
1014 if (!tmp) /* discard empty sub-blocks */
1015 return SILC_CONFIG_OK;
1017 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
1019 return SILC_CONFIG_OK;
1021 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
1023 /* Identify and save this value */
1024 if (!strcmp(name, "host")) {
1025 CONFIG_IS_DOUBLE(tmp->host);
1026 tmp->host = strdup((char *) val);
1028 else if (!strcmp(name, "port")) {
1029 int port = *(int *)val;
1030 if ((port <= 0) || (port > 65535)) {
1031 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1032 "Invalid port number!"));
1033 got_errno = SILC_CONFIG_EPRINTLINE;
1036 tmp->port = (SilcUInt16) port;
1038 else if (!strcmp(name, "passphrase")) {
1039 CONFIG_IS_DOUBLE(tmp->passphrase);
1040 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1041 (void **)&tmp->passphrase,
1042 &tmp->passphrase_len)) {
1043 got_errno = SILC_CONFIG_EPRINTLINE;
1047 else if (!strcmp(name, "publickey")) {
1048 CONFIG_IS_DOUBLE(tmp->publickeys);
1049 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1050 (void **)&tmp->publickeys, NULL)) {
1051 got_errno = SILC_CONFIG_EPRINTLINE;
1055 else if (!strcmp(name, "params")) {
1056 CONFIG_IS_DOUBLE(tmp->param);
1057 tmp->param = my_find_param(config, (char *) val);
1058 if (!tmp->param) { /* error message already output */
1059 got_errno = SILC_CONFIG_EPRINTLINE;
1063 else if (!strcmp(name, "initiator")) {
1064 tmp->initiator = *(bool *)val;
1066 else if (!strcmp(name, "backuphost")) {
1067 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
1068 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
1070 tmp->backup_router = TRUE;
1072 else if (!strcmp(name, "backupport")) {
1073 int port = *(int *)val;
1074 if ((port <= 0) || (port > 65535)) {
1075 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1076 "Invalid port number!"));
1077 got_errno = SILC_CONFIG_EPRINTLINE;
1080 tmp->backup_replace_port = (SilcUInt16) port;
1082 else if (!strcmp(name, "backuplocal")) {
1083 tmp->backup_local = *(bool *)val;
1086 return SILC_CONFIG_EINTERNAL;
1088 return SILC_CONFIG_OK;
1091 silc_free(tmp->host);
1092 silc_free(tmp->backup_replace_ip);
1093 CONFIG_FREE_AUTH(tmp);
1099 /* known config options tables */
1100 static const SilcConfigTable table_general[] = {
1101 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1102 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1103 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1104 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1105 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1106 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1107 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1108 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1109 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1110 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1111 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1112 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1113 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1114 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1115 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1116 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1117 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1118 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1119 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1120 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1121 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1122 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1123 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1124 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1125 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1129 static const SilcConfigTable table_cipher[] = {
1130 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1131 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1132 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1133 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1137 static const SilcConfigTable table_hash[] = {
1138 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1139 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1140 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1141 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1145 static const SilcConfigTable table_hmac[] = {
1146 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1147 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1148 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1152 static const SilcConfigTable table_pkcs[] = {
1153 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1157 static const SilcConfigTable table_serverinfo_c[] = {
1158 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1159 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1163 static const SilcConfigTable table_serverinfo[] = {
1164 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1165 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1166 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1167 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1168 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1169 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1170 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1171 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1172 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1173 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1174 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1175 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1176 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1180 static const SilcConfigTable table_logging_c[] = {
1181 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1182 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1183 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1187 static const SilcConfigTable table_logging[] = {
1188 { "timestamp", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1189 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1190 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1191 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1192 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1193 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1194 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1198 static const SilcConfigTable table_connparam[] = {
1199 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1200 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1201 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1202 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1203 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1204 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1205 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1206 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1207 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1208 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1209 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1210 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1211 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1212 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1213 { "anonymous", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1214 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1215 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1216 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1217 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1218 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1222 static const SilcConfigTable table_client[] = {
1223 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1224 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1225 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1226 { "publickeydir", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1227 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1231 static const SilcConfigTable table_admin[] = {
1232 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1233 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1234 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1235 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1236 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1237 { "publickeydir", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1238 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1239 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1243 static const SilcConfigTable table_deny[] = {
1244 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1245 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1249 static const SilcConfigTable table_serverconn[] = {
1250 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1251 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1252 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1253 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1254 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1258 static const SilcConfigTable table_routerconn[] = {
1259 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1260 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1261 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1262 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1263 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1264 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1265 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1266 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1267 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1271 static const SilcConfigTable table_main[] = {
1272 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1273 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1274 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1275 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1276 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1277 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1278 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1279 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1280 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1281 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1282 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1283 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1284 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1288 /* Set default values to stuff that was not configured. */
1290 static void silc_server_config_set_defaults(SilcServerConfig config)
1292 my_set_param_defaults(&config->param, NULL);
1294 config->channel_rekey_secs = (config->channel_rekey_secs ?
1295 config->channel_rekey_secs :
1296 SILC_SERVER_CHANNEL_REKEY);
1297 config->key_exchange_timeout = (config->key_exchange_timeout ?
1298 config->key_exchange_timeout :
1299 SILC_SERVER_SKE_TIMEOUT);
1300 config->conn_auth_timeout = (config->conn_auth_timeout ?
1301 config->conn_auth_timeout :
1302 SILC_SERVER_CONNAUTH_TIMEOUT);
1305 /* Allocates a new configuration object, opens configuration file and
1306 parses it. The parsed data is returned to the newly allocated
1307 configuration object. The SilcServerConfig must be freed by calling
1308 the silc_server_config_destroy function. */
1310 SilcServerConfig silc_server_config_alloc(const char *filename)
1312 SilcServerConfig config_new;
1313 SilcConfigEntity ent;
1314 SilcConfigFile *file;
1316 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1318 /* alloc a config object */
1319 config_new = silc_calloc(1, sizeof(*config_new));
1323 /* general config defaults */
1324 config_new->refcount = 1;
1325 config_new->logging_timestamp = TRUE;
1327 /* obtain a config file object */
1328 file = silc_config_open(filename);
1330 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
1335 /* obtain a SilcConfig entity, we can use it to start the parsing */
1336 ent = silc_config_init(file);
1338 /* load the known configuration options, give our empty object as context */
1339 silc_config_register_table(ent, table_main, (void *) config_new);
1341 /* enter the main parsing loop. When this returns, we have the parsing
1342 * result and the object filled (or partially, in case of errors). */
1343 ret = silc_config_main(ent);
1344 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1345 silc_config_strerror(ret)));
1347 /* Check if the parser returned errors */
1349 /* handle this special error return which asks to quietly return */
1350 if (ret != SILC_CONFIG_ESILENT) {
1351 char *linebuf, *filename = silc_config_get_filename(file);
1352 SilcUInt32 line = silc_config_get_line(file);
1353 if (ret != SILC_CONFIG_EPRINTLINE)
1354 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
1355 silc_config_strerror(ret)));
1356 linebuf = silc_config_read_line(file, line);
1357 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1361 silc_server_config_destroy(config_new);
1365 /* close (destroy) the file object */
1366 silc_config_close(file);
1368 /* If config_new is incomplete, abort the object and return NULL */
1369 if (!config_new->server_info) {
1370 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1372 silc_server_config_destroy(config_new);
1376 /* Set default to configuration parameters */
1377 silc_server_config_set_defaults(config_new);
1382 /* Increments the reference counter of a config object */
1384 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1389 ref->config = config;
1390 ref->ref_ptr = ref_ptr;
1391 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1392 config->refcount - 1, config->refcount));
1396 /* Decrements the reference counter of a config object. If the counter
1397 reaches 0, the config object is destroyed. */
1399 void silc_server_config_unref(SilcServerConfigRef *ref)
1402 silc_server_config_destroy(ref->config);
1405 /* Destroy a config object with all his children lists */
1407 void silc_server_config_destroy(SilcServerConfig config)
1412 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1413 config->refcount + 1, config->refcount));
1414 if (config->refcount > 0)
1417 SILC_LOG_DEBUG(("Freeing config context"));
1419 /* Destroy general config stuff */
1420 silc_free(config->module_path);
1421 silc_free(config->param.version_protocol);
1422 silc_free(config->param.version_software);
1423 silc_free(config->param.version_software_vendor);
1425 /* Destroy Logging channels */
1426 if (config->logging_info)
1427 silc_free(config->logging_info->file);
1428 if (config->logging_warnings)
1429 silc_free(config->logging_warnings->file);
1430 if (config->logging_errors)
1431 silc_free(config->logging_errors->file);
1432 if (config->logging_fatals)
1433 silc_free(config->logging_fatals->file);
1434 silc_free(config->logging_info);
1435 silc_free(config->logging_warnings);
1436 silc_free(config->logging_errors);
1437 silc_free(config->logging_fatals);
1439 /* Destroy the ServerInfo struct */
1440 if (config->server_info) {
1441 register SilcServerConfigServerInfo *si = config->server_info;
1442 silc_free(si->server_name);
1444 silc_free(si->primary->server_ip);
1445 silc_free(si->primary);
1447 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1449 silc_free(di->server_ip);
1452 silc_free(si->server_type);
1453 silc_free(si->location);
1454 silc_free(si->admin);
1455 silc_free(si->email);
1456 silc_free(si->user);
1457 silc_free(si->group);
1458 silc_free(si->motd_file);
1459 silc_free(si->pid_file);
1460 silc_pkcs_public_key_free(si->public_key);
1461 silc_pkcs_private_key_free(si->private_key);
1465 /* Now let's destroy the lists */
1467 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1469 silc_free(di->name);
1470 silc_free(di->module);
1473 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1474 silc_free(di->name);
1475 silc_free(di->module);
1478 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1479 silc_free(di->name);
1480 silc_free(di->hash);
1483 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1484 silc_free(di->name);
1487 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1488 config->conn_params)
1489 silc_free(di->name);
1490 silc_free(di->version_protocol);
1491 silc_free(di->version_software);
1492 silc_free(di->version_software_vendor);
1495 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1496 silc_free(di->host);
1497 CONFIG_FREE_AUTH(di);
1500 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1501 silc_free(di->host);
1502 silc_free(di->user);
1503 silc_free(di->nick);
1504 CONFIG_FREE_AUTH(di);
1507 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1508 silc_free(di->host);
1509 silc_free(di->reason);
1512 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1514 silc_free(di->host);
1515 CONFIG_FREE_AUTH(di);
1518 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1520 silc_free(di->host);
1521 silc_free(di->backup_replace_ip);
1522 CONFIG_FREE_AUTH(di);
1526 memset(config, 'F', sizeof(*config));
1530 /* Registers configured ciphers. These can then be allocated by the
1531 server when needed. */
1533 bool silc_server_config_register_ciphers(SilcServer server)
1535 SilcServerConfig config = server->config;
1536 SilcServerConfigCipher *cipher = config->cipher;
1537 char *module_path = config->module_path;
1539 SILC_LOG_DEBUG(("Registering configured ciphers"));
1541 if (!cipher) /* any cipher in the config file? */
1545 /* if there isn't a module_path OR there isn't a module sim name try to
1546 * use buil-in functions */
1547 if (!module_path || !cipher->module) {
1549 for (i = 0; silc_default_ciphers[i].name; i++)
1550 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1551 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1554 if (!silc_cipher_is_supported(cipher->name)) {
1555 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1556 silc_server_stop(server);
1561 /* Load (try at least) the crypto SIM module */
1562 char buf[1023], *alg_name;
1563 SilcCipherObject cipher_obj;
1566 memset(&cipher_obj, 0, sizeof(cipher_obj));
1567 cipher_obj.name = cipher->name;
1568 cipher_obj.block_len = cipher->block_length;
1569 cipher_obj.key_len = cipher->key_length * 8;
1571 /* build the libname */
1572 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1574 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1576 alg_name = strdup(cipher->name);
1577 if (strchr(alg_name, '-'))
1578 *strchr(alg_name, '-') = '\0';
1580 if (silc_sim_load(sim)) {
1581 cipher_obj.set_key =
1582 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1583 SILC_CIPHER_SIM_SET_KEY));
1584 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1585 cipher_obj.set_key_with_string =
1586 silc_sim_getsym(sim,
1587 silc_sim_symname(alg_name,
1588 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1589 SILC_LOG_DEBUG(("set_key_with_string=%p",
1590 cipher_obj.set_key_with_string));
1591 cipher_obj.encrypt =
1592 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1593 SILC_CIPHER_SIM_ENCRYPT_CBC));
1594 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1595 cipher_obj.decrypt =
1596 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1597 SILC_CIPHER_SIM_DECRYPT_CBC));
1598 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1599 cipher_obj.context_len =
1600 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1601 SILC_CIPHER_SIM_CONTEXT_LEN));
1602 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1604 /* Put the SIM to the list of all SIM's in server */
1605 silc_dlist_add(server->sim, sim);
1607 silc_free(alg_name);
1609 SILC_LOG_ERROR(("Error configuring ciphers"));
1611 silc_server_stop(server);
1615 /* Register the cipher */
1616 silc_cipher_register(&cipher_obj);
1618 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1619 "can't load modules!"));
1620 silc_server_stop(server);
1624 cipher = cipher->next;
1630 /* Registers configured hash functions. These can then be allocated by the
1631 server when needed. */
1633 bool silc_server_config_register_hashfuncs(SilcServer server)
1635 SilcServerConfig config = server->config;
1636 SilcServerConfigHash *hash = config->hash;
1637 char *module_path = config->module_path;
1639 SILC_LOG_DEBUG(("Registering configured hash functions"));
1641 if (!hash) /* any hash func in the config file? */
1645 /* if there isn't a module_path OR there isn't a module sim name try to
1646 * use buil-in functions */
1647 if (!module_path || !hash->module) {
1649 for (i = 0; silc_default_hash[i].name; i++)
1650 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1651 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1654 if (!silc_hash_is_supported(hash->name)) {
1655 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1656 silc_server_stop(server);
1661 /* Load (try at least) the hash SIM module */
1662 SilcHashObject hash_obj;
1665 memset(&hash_obj, 0, sizeof(hash_obj));
1666 hash_obj.name = hash->name;
1667 hash_obj.block_len = hash->block_length;
1668 hash_obj.hash_len = hash->digest_length;
1670 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1672 if ((silc_sim_load(sim))) {
1674 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1675 SILC_HASH_SIM_INIT));
1676 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1678 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1679 SILC_HASH_SIM_UPDATE));
1680 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1682 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1683 SILC_HASH_SIM_FINAL));
1684 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1685 hash_obj.context_len =
1686 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1687 SILC_HASH_SIM_CONTEXT_LEN));
1688 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1690 /* Put the SIM to the table of all SIM's in server */
1691 silc_dlist_add(server->sim, sim);
1693 SILC_LOG_ERROR(("Error configuring hash functions"));
1695 silc_server_stop(server);
1699 /* Register the hash function */
1700 silc_hash_register(&hash_obj);
1702 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1703 "can't load modules!"));
1704 silc_server_stop(server);
1714 /* Registers configure HMACs. These can then be allocated by the server
1717 bool silc_server_config_register_hmacs(SilcServer server)
1719 SilcServerConfig config = server->config;
1720 SilcServerConfigHmac *hmac = config->hmac;
1722 SILC_LOG_DEBUG(("Registering configured HMACs"));
1728 SilcHmacObject hmac_obj;
1729 if (!silc_hash_is_supported(hmac->hash)) {
1730 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1731 silc_server_stop(server);
1735 /* Register the HMAC */
1736 memset(&hmac_obj, 0, sizeof(hmac_obj));
1737 hmac_obj.name = hmac->name;
1738 hmac_obj.len = hmac->mac_length;
1739 silc_hmac_register(&hmac_obj);
1747 /* Registers configured PKCS's. */
1749 bool silc_server_config_register_pkcs(SilcServer server)
1751 SilcServerConfig config = server->config;
1752 SilcServerConfigPkcs *pkcs = config->pkcs;
1754 SILC_LOG_DEBUG(("Registering configured PKCS"));
1761 for (i = 0; silc_default_pkcs[i].name; i++)
1762 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1763 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1766 if (!silc_pkcs_is_supported(pkcs->name)) {
1767 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1768 silc_server_stop(server);
1777 /* Sets log files where log messages are saved by the server logger. */
1779 void silc_server_config_setlogfiles(SilcServer server)
1781 SilcServerConfig config = server->config;
1782 SilcServerConfigLogging *this;
1784 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1786 silc_log_timestamp = config->logging_timestamp;
1787 silc_log_quick = config->logging_quick;
1788 silc_log_flushdelay = (config->logging_flushdelay ?
1789 config->logging_flushdelay :
1790 SILC_SERVER_LOG_FLUSH_DELAY);
1792 if ((this = config->logging_fatals))
1793 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1795 if ((this = config->logging_errors))
1796 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1798 if ((this = config->logging_warnings))
1799 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1801 if ((this = config->logging_info))
1802 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1806 /* Returns client authentication information from configuration file by host
1809 SilcServerConfigClient *
1810 silc_server_config_find_client(SilcServer server, char *host)
1812 SilcServerConfig config = server->config;
1813 SilcServerConfigClient *client;
1815 if (!config || !host)
1818 for (client = config->clients; client; client = client->next) {
1819 if (client->host && !silc_string_compare(client->host, host))
1824 /* if none matched, then client is already NULL */
1828 /* Returns admin connection configuration by host, username and/or
1831 SilcServerConfigAdmin *
1832 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1835 SilcServerConfig config = server->config;
1836 SilcServerConfigAdmin *admin;
1838 /* make sure we have a value for the matching parameters */
1846 for (admin = config->admins; admin; admin = admin->next) {
1847 if (admin->host && !silc_string_compare(admin->host, host))
1849 if (admin->user && !silc_string_compare(admin->user, user))
1851 if (admin->nick && !silc_string_compare(admin->nick, nick))
1853 /* no checks failed -> this entry matches */
1857 /* if none matched, then admin is already NULL */
1861 /* Returns the denied connection configuration entry by host. */
1863 SilcServerConfigDeny *
1864 silc_server_config_find_denied(SilcServer server, char *host)
1866 SilcServerConfig config = server->config;
1867 SilcServerConfigDeny *deny;
1869 /* make sure we have a value for the matching parameters */
1870 if (!config || !host)
1873 for (deny = config->denied; deny; deny = deny->next) {
1874 if (deny->host && !silc_string_compare(deny->host, host))
1879 /* if none matched, then deny is already NULL */
1883 /* Returns server connection info from server configuartion by host
1886 SilcServerConfigServer *
1887 silc_server_config_find_server_conn(SilcServer server, char *host)
1889 SilcServerConfig config = server->config;
1890 SilcServerConfigServer *serv = NULL;
1895 if (!config->servers)
1898 for (serv = config->servers; serv; serv = serv->next) {
1899 if (!silc_string_compare(serv->host, host))
1907 /* Returns router connection info from server configuration by
1908 host (name or ip). */
1910 SilcServerConfigRouter *
1911 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1913 SilcServerConfig config = server->config;
1914 SilcServerConfigRouter *serv = NULL;
1919 if (!config->routers)
1922 for (serv = config->routers; serv; serv = serv->next) {
1923 if (!silc_string_compare(serv->host, host))
1925 if (port && serv->port && serv->port != port)
1933 /* Find backup router connection by host (name or ip) */
1935 SilcServerConfigRouter *
1936 silc_server_config_find_backup_conn(SilcServer server, char *host)
1938 SilcServerConfig config = server->config;
1939 SilcServerConfigRouter *serv = NULL;
1944 if (!config->routers)
1947 for (serv = config->routers; serv; serv = serv->next) {
1948 if (!serv->backup_router)
1950 if (!silc_string_compare(serv->host, host))
1958 /* Returns TRUE if configuration for a router connection that we are
1959 initiating exists. */
1961 bool silc_server_config_is_primary_route(SilcServer server)
1963 SilcServerConfig config = server->config;
1964 SilcServerConfigRouter *serv = NULL;
1968 serv = config->routers;
1969 for (i = 0; serv; i++) {
1970 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1981 /* Returns our primary connection configuration or NULL if we do not
1982 have primary router configured. */
1984 SilcServerConfigRouter *
1985 silc_server_config_get_primary_router(SilcServer server)
1987 SilcServerConfig config = server->config;
1988 SilcServerConfigRouter *serv = NULL;
1991 serv = config->routers;
1992 for (i = 0; serv; i++) {
1993 if (serv->initiator == TRUE && serv->backup_router == FALSE)
2001 /* If we have backup router configured that is going to replace us this
2002 function returns it. */
2004 SilcServerConfigRouter *
2005 silc_server_config_get_backup_router(SilcServer server)
2007 SilcServerConfig config = server->config;
2008 SilcServerConfigRouter *serv = NULL;
2011 if (server->server_type != SILC_ROUTER)
2014 serv = config->routers;
2015 for (i = 0; serv; i++) {
2016 if (serv->initiator == FALSE && serv->backup_router == TRUE &&
2017 serv->backup_local == TRUE &&
2018 !strcmp(server->config->server_info->primary->server_ip,
2019 serv->backup_replace_ip) &&
2020 server->config->server_info->primary->port ==
2021 serv->backup_replace_port)