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"
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); \
71 if (__section__->publickeys) \
72 silc_hash_table_free(__section__->publickeys);
74 static void my_free_public_key(void *key, void *context, void *user_data)
76 silc_pkcs_public_key_free(context);
79 /* Set default values to those parameters that have not been defined */
81 my_set_param_defaults(SilcServerConfigConnParams *params,
82 SilcServerConfigConnParams *defaults)
84 #define SET_PARAM_DEFAULT(p, d) params->p = \
85 (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
87 SET_PARAM_DEFAULT(connections_max, SILC_SERVER_MAX_CONNECTIONS);
88 SET_PARAM_DEFAULT(connections_max_per_host,
89 SILC_SERVER_MAX_CONNECTIONS_SINGLE);
90 SET_PARAM_DEFAULT(keepalive_secs, SILC_SERVER_KEEPALIVE);
91 SET_PARAM_DEFAULT(reconnect_count, SILC_SERVER_RETRY_COUNT);
92 SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
93 SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
94 SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
96 #undef SET_PARAM_DEFAULT
99 /* Find connection parameters by the parameter block name. */
100 static SilcServerConfigConnParams *
101 my_find_param(SilcServerConfig config, const char *name)
103 SilcServerConfigConnParams *param;
105 for (param = config->conn_params; param; param = param->next) {
106 if (!strcasecmp(param->name, name))
110 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
111 "Cannot find Params \"%s\".\n", name));
116 /* parse an authdata according to its auth method */
117 static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
118 SilcUInt32 line, void **auth_data,
119 SilcUInt32 *auth_data_len)
121 if (auth_meth == SILC_AUTH_PASSWORD) {
122 /* p is a plain text password */
123 if (auth_data && auth_data_len) {
124 if (!silc_utf8_valid(p, strlen(p))) {
125 *auth_data_len = silc_utf8_encoded_len(p, strlen(p),
126 SILC_STRING_LANGUAGE);
127 *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
128 silc_utf8_encode(p, strlen(p), SILC_STRING_LANGUAGE, *auth_data,
131 *auth_data = (void *) strdup(p);
132 *auth_data_len = (SilcUInt32) strlen(p);
135 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
136 /* p is a public key file name */
137 SilcPublicKey public_key;
139 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
140 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
141 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line "
142 "%lu: Could not load public key file!\n",
147 /* The auth_data is a pointer to the hash table of public keys. */
149 if (*auth_data == NULL)
150 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
152 my_free_public_key, NULL,
154 silc_hash_table_add(*auth_data, public_key, public_key);
157 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
158 "Unknown authentication method.\n", line));
166 SILC_CONFIG_CALLBACK(fetch_generic)
168 SilcServerConfig config = (SilcServerConfig) context;
171 if (!strcmp(name, "module_path")) {
172 CONFIG_IS_DOUBLE(config->module_path);
173 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
175 else if (!strcmp(name, "prefer_passphrase_auth")) {
176 config->prefer_passphrase_auth = *(bool *)val;
178 else if (!strcmp(name, "require_reverse_lookup")) {
179 config->require_reverse_lookup = *(bool *)val;
181 else if (!strcmp(name, "connections_max")) {
182 config->param.connections_max = (SilcUInt32) *(int *)val;
184 else if (!strcmp(name, "connections_max_per_host")) {
185 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
187 else if (!strcmp(name, "keepalive_secs")) {
188 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
190 else if (!strcmp(name, "reconnect_count")) {
191 config->param.reconnect_count = (SilcUInt32) *(int *)val;
193 else if (!strcmp(name, "reconnect_interval")) {
194 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
196 else if (!strcmp(name, "reconnect_interval_max")) {
197 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
199 else if (!strcmp(name, "reconnect_keep_trying")) {
200 config->param.reconnect_keep_trying = *(bool *)val;
202 else if (!strcmp(name, "key_exchange_rekey")) {
203 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
205 else if (!strcmp(name, "key_exchange_pfs")) {
206 config->param.key_exchange_pfs = *(bool *)val;
208 else if (!strcmp(name, "channel_rekey_secs")) {
209 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
211 else if (!strcmp(name, "key_exchange_timeout")) {
212 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
214 else if (!strcmp(name, "conn_auth_timeout")) {
215 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
217 else if (!strcmp(name, "version_protocol")) {
218 CONFIG_IS_DOUBLE(config->param.version_protocol);
219 config->param.version_protocol =
220 (*(char *)val ? strdup((char *) val) : NULL);
222 else if (!strcmp(name, "version_software")) {
223 CONFIG_IS_DOUBLE(config->param.version_software);
224 config->param.version_software =
225 (*(char *)val ? strdup((char *) val) : NULL);
227 else if (!strcmp(name, "version_software_vendor")) {
228 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
229 config->param.version_software_vendor =
230 (*(char *)val ? strdup((char *) val) : NULL);
232 else if (!strcmp(name, "detach_disabled")) {
233 config->detach_disabled = *(bool *)val;
235 else if (!strcmp(name, "detach_timeout")) {
236 config->detach_timeout = (SilcUInt32) *(int *)val;
239 return SILC_CONFIG_EINTERNAL;
241 return SILC_CONFIG_OK;
247 SILC_CONFIG_CALLBACK(fetch_cipher)
249 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
251 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
252 type, name, context));
253 if (type == SILC_CONFIG_ARG_BLOCK) {
254 /* check the temporary struct's fields */
255 if (!tmp) /* discard empty sub-blocks */
256 return SILC_CONFIG_OK;
258 got_errno = SILC_CONFIG_EMISSFIELDS;
262 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
264 return SILC_CONFIG_OK;
266 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
268 /* Identify and save this value */
269 if (!strcmp(name, "name")) {
270 CONFIG_IS_DOUBLE(tmp->name);
271 tmp->name = strdup((char *) val);
273 else if (!strcmp(name, "module")) {
274 CONFIG_IS_DOUBLE(tmp->module);
275 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
277 else if (!strcmp(name, "keylength")) {
278 tmp->key_length = *(SilcUInt32 *)val;
280 else if (!strcmp(name, "blocklength")) {
281 tmp->block_length = *(SilcUInt32 *)val;
284 return SILC_CONFIG_EINTERNAL;
285 return SILC_CONFIG_OK;
288 silc_free(tmp->name);
289 silc_free(tmp->module);
295 SILC_CONFIG_CALLBACK(fetch_hash)
297 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
299 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
300 type, name, context));
301 if (type == SILC_CONFIG_ARG_BLOCK) {
302 /* check the temporary struct's fields */
303 if (!tmp) /* discard empty sub-blocks */
304 return SILC_CONFIG_OK;
305 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
306 got_errno = SILC_CONFIG_EMISSFIELDS;
310 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
312 return SILC_CONFIG_OK;
314 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
316 /* Identify and save this value */
317 if (!strcmp(name, "name")) {
318 CONFIG_IS_DOUBLE(tmp->name);
319 tmp->name = strdup((char *) val);
321 else if (!strcmp(name, "module")) {
322 CONFIG_IS_DOUBLE(tmp->module);
323 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
325 else if (!strcmp(name, "blocklength")) {
326 tmp->block_length = *(int *)val;
328 else if (!strcmp(name, "digestlength")) {
329 tmp->digest_length = *(int *)val;
332 return SILC_CONFIG_EINTERNAL;
333 return SILC_CONFIG_OK;
336 silc_free(tmp->name);
337 silc_free(tmp->module);
343 SILC_CONFIG_CALLBACK(fetch_hmac)
345 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
347 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
348 type, name, context));
349 if (type == SILC_CONFIG_ARG_BLOCK) {
350 /* check the temporary struct's fields */
351 if (!tmp) /* discard empty sub-blocks */
352 return SILC_CONFIG_OK;
353 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
354 got_errno = SILC_CONFIG_EMISSFIELDS;
358 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
360 return SILC_CONFIG_OK;
362 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
364 /* Identify and save this value */
365 if (!strcmp(name, "name")) {
366 CONFIG_IS_DOUBLE(tmp->name);
367 tmp->name = strdup((char *) val);
369 else if (!strcmp(name, "hash")) {
370 CONFIG_IS_DOUBLE(tmp->hash);
371 tmp->hash = strdup((char *) val);
373 else if (!strcmp(name, "maclength")) {
374 tmp->mac_length = *(int *)val;
377 return SILC_CONFIG_EINTERNAL;
378 return SILC_CONFIG_OK;
381 silc_free(tmp->name);
382 silc_free(tmp->hash);
388 SILC_CONFIG_CALLBACK(fetch_pkcs)
390 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
392 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
393 type, name, context));
394 if (type == SILC_CONFIG_ARG_BLOCK) {
395 /* check the temporary struct's fields */
396 if (!tmp) /* discard empty sub-blocks */
397 return SILC_CONFIG_OK;
399 got_errno = SILC_CONFIG_EMISSFIELDS;
403 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
405 return SILC_CONFIG_OK;
407 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
409 /* Identify and save this value */
410 if (!strcmp(name, "name")) {
411 CONFIG_IS_DOUBLE(tmp->name);
412 tmp->name = strdup((char *) val);
415 return SILC_CONFIG_EINTERNAL;
416 return SILC_CONFIG_OK;
419 silc_free(tmp->name);
425 SILC_CONFIG_CALLBACK(fetch_serverinfo)
427 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
428 SilcServerConfigServerInfo *server_info = config->server_info;
430 /* if there isn't the struct alloc it */
432 config->server_info = server_info = (SilcServerConfigServerInfo *)
433 silc_calloc(1, sizeof(*server_info));
435 if (type == SILC_CONFIG_ARG_BLOCK) {
436 if (!strcmp(name, "primary")) {
437 CONFIG_IS_DOUBLE(server_info->primary);
439 return SILC_CONFIG_OK;
440 server_info->primary = tmp;
442 return SILC_CONFIG_OK;
443 } else if (!strcmp(name, "secondary")) {
445 return SILC_CONFIG_OK;
446 SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
448 return SILC_CONFIG_OK;
449 } else if (!server_info->public_key || !server_info->private_key) {
450 got_errno = SILC_CONFIG_EMISSFIELDS;
453 return SILC_CONFIG_OK;
455 if (!strcmp(name, "hostname")) {
456 CONFIG_IS_DOUBLE(server_info->server_name);
457 server_info->server_name = strdup((char *) val);
459 else if (!strcmp(name, "ip")) {
460 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
461 CONFIG_IS_DOUBLE(tmp->server_ip);
462 tmp->server_ip = strdup((char *) val);
464 else if (!strcmp(name, "port")) {
465 int port = *(int *)val;
466 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
467 if ((port <= 0) || (port > 65535)) {
468 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
469 "Invalid port number!\n"));
470 got_errno = SILC_CONFIG_EPRINTLINE;
473 tmp->port = (SilcUInt16) port;
475 else if (!strcmp(name, "servertype")) {
476 CONFIG_IS_DOUBLE(server_info->server_type);
477 server_info->server_type = strdup((char *) val);
479 else if (!strcmp(name, "admin")) {
480 CONFIG_IS_DOUBLE(server_info->admin);
481 server_info->admin = strdup((char *) val);
483 else if (!strcmp(name, "adminemail")) {
484 CONFIG_IS_DOUBLE(server_info->email);
485 server_info->email = strdup((char *) val);
487 else if (!strcmp(name, "location")) {
488 CONFIG_IS_DOUBLE(server_info->location);
489 server_info->location = strdup((char *) val);
491 else if (!strcmp(name, "user")) {
492 CONFIG_IS_DOUBLE(server_info->user);
493 server_info->user = strdup((char *) val);
495 else if (!strcmp(name, "group")) {
496 CONFIG_IS_DOUBLE(server_info->group);
497 server_info->group = strdup((char *) val);
499 else if (!strcmp(name, "motdfile")) {
500 CONFIG_IS_DOUBLE(server_info->motd_file);
501 server_info->motd_file = strdup((char *) val);
503 else if (!strcmp(name, "pidfile")) {
504 CONFIG_IS_DOUBLE(server_info->pid_file);
505 server_info->pid_file = strdup((char *) val);
507 else if (!strcmp(name, "publickey")) {
508 char *file_tmp = (char *) val;
510 /* try to load specified file, if fail stop config parsing */
511 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
513 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
514 SILC_PKCS_FILE_BIN)) {
515 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n"));
516 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
517 return SILC_CONFIG_ESILENT;
520 else if (!strcmp(name, "privatekey")) {
521 char *file_tmp = (char *) val;
523 /* try to load specified file, if fail stop config parsing */
524 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
526 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
527 SILC_PKCS_FILE_PEM)) {
528 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n"));
529 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
530 return SILC_CONFIG_ESILENT;
534 return SILC_CONFIG_EINTERNAL;
535 return SILC_CONFIG_OK;
539 silc_free(config->tmp);
544 SILC_CONFIG_CALLBACK(fetch_logging)
546 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
548 if (!strcmp(name, "quicklogs")) {
549 config->logging_quick = *(bool *)val;
551 else if (!strcmp(name, "flushdelay")) {
552 int flushdelay = *(int *)val;
553 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
554 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
555 "Invalid flushdelay value, use quicklogs if you "
556 "want real-time logging.\n"));
557 return SILC_CONFIG_EPRINTLINE;
559 config->logging_flushdelay = (long) flushdelay;
562 /* The following istances happens only in Logging's sub-blocks, a match
563 for the sub-block name means that you should store the filename/maxsize
564 temporary struct to the proper logging channel.
565 If we get a match for "file" or "maxsize" this means that we are inside
566 a sub-sub-block and it is safe to alloc a new tmp. */
567 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
568 else if (!strcmp(name, __chan__)) { \
569 if (!tmp) return SILC_CONFIG_OK; \
571 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
573 config->__member__ = tmp; \
574 config->tmp = NULL; \
576 FETCH_LOGGING_CHAN("info", logging_info)
577 FETCH_LOGGING_CHAN("warnings", logging_warnings)
578 FETCH_LOGGING_CHAN("errors", logging_errors)
579 FETCH_LOGGING_CHAN("fatals", logging_fatals)
580 #undef FETCH_LOGGING_CHAN
581 else if (!strcmp(name, "file")) {
582 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
583 CONFIG_IS_DOUBLE(tmp->file);
584 tmp->file = strdup((char *) val);
586 else if (!strcmp(name, "size")) {
588 config->tmp = silc_calloc(1, sizeof(*tmp));
589 tmp = (SilcServerConfigLogging *) config->tmp;
591 tmp->maxsize = *(SilcUInt32 *) val;
594 return SILC_CONFIG_EINTERNAL;
595 return SILC_CONFIG_OK;
598 silc_free(tmp->file);
604 SILC_CONFIG_CALLBACK(fetch_connparam)
606 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
608 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
609 type, name, context));
610 if (type == SILC_CONFIG_ARG_BLOCK) {
611 /* check the temporary struct's fields */
612 if (!tmp) /* discard empty sub-blocks */
613 return SILC_CONFIG_OK;
615 got_errno = SILC_CONFIG_EMISSFIELDS;
619 my_set_param_defaults(tmp, &config->param);
621 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
623 return SILC_CONFIG_OK;
625 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
627 if (!strcmp(name, "name")) {
628 CONFIG_IS_DOUBLE(tmp->name);
629 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
631 else if (!strcmp(name, "connections_max")) {
632 tmp->connections_max = *(SilcUInt32 *)val;
634 else if (!strcmp(name, "connections_max_per_host")) {
635 tmp->connections_max_per_host = *(SilcUInt32 *)val;
637 else if (!strcmp(name, "keepalive_secs")) {
638 tmp->keepalive_secs = *(SilcUInt32 *)val;
640 else if (!strcmp(name, "reconnect_count")) {
641 tmp->reconnect_count = *(SilcUInt32 *)val;
643 else if (!strcmp(name, "reconnect_interval")) {
644 tmp->reconnect_interval = *(SilcUInt32 *)val;
646 else if (!strcmp(name, "reconnect_interval_max")) {
647 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
649 else if (!strcmp(name, "reconnect_keep_trying")) {
650 tmp->reconnect_keep_trying = *(bool *)val;
652 else if (!strcmp(name, "key_exchange_rekey")) {
653 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
655 else if (!strcmp(name, "key_exchange_pfs")) {
656 tmp->key_exchange_pfs = *(bool *)val;
658 else if (!strcmp(name, "version_protocol")) {
659 CONFIG_IS_DOUBLE(tmp->version_protocol);
660 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
662 else if (!strcmp(name, "version_software")) {
663 CONFIG_IS_DOUBLE(tmp->version_software);
664 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
666 else if (!strcmp(name, "version_software_vendor")) {
667 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
668 tmp->version_software_vendor =
669 (*(char *)val ? strdup((char *) val) : NULL);
672 return SILC_CONFIG_EINTERNAL;
674 return SILC_CONFIG_OK;
677 silc_free(tmp->name);
683 SILC_CONFIG_CALLBACK(fetch_client)
685 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
687 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
688 type, name, context));
690 /* Alloc before block checking, because empty sub-blocks are welcome here */
691 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
693 if (type == SILC_CONFIG_ARG_BLOCK) {
694 /* empty sub-blocks are welcome */
695 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
697 return SILC_CONFIG_OK;
700 /* Identify and save this value */
701 if (!strcmp(name, "host")) {
702 CONFIG_IS_DOUBLE(tmp->host);
703 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
705 else if (!strcmp(name, "passphrase")) {
706 CONFIG_IS_DOUBLE(tmp->passphrase);
707 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
708 (void **)&tmp->passphrase,
709 &tmp->passphrase_len)) {
710 got_errno = SILC_CONFIG_ESILENT;
714 else if (!strcmp(name, "publickey")) {
715 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
716 (void **)&tmp->publickeys, NULL)) {
717 got_errno = SILC_CONFIG_ESILENT;
721 else if (!strcmp(name, "params")) {
722 CONFIG_IS_DOUBLE(tmp->param);
723 tmp->param = my_find_param(config, (char *) val);
724 if (!tmp->param) { /* error message already output */
725 got_errno = SILC_CONFIG_EPRINTLINE;
730 return SILC_CONFIG_EINTERNAL;
731 return SILC_CONFIG_OK;
734 silc_free(tmp->host);
735 CONFIG_FREE_AUTH(tmp);
741 SILC_CONFIG_CALLBACK(fetch_admin)
743 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
745 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
746 type, name, context));
747 if (type == SILC_CONFIG_ARG_BLOCK) {
748 /* check the temporary struct's fields */
749 if (!tmp) /* discard empty sub-blocks */
750 return SILC_CONFIG_OK;
752 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
754 return SILC_CONFIG_OK;
756 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
758 /* Identify and save this value */
759 if (!strcmp(name, "host")) {
760 CONFIG_IS_DOUBLE(tmp->host);
761 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
763 else if (!strcmp(name, "user")) {
764 CONFIG_IS_DOUBLE(tmp->user);
765 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
767 else if (!strcmp(name, "nick")) {
768 CONFIG_IS_DOUBLE(tmp->nick);
769 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
771 else if (!strcmp(name, "passphrase")) {
772 CONFIG_IS_DOUBLE(tmp->passphrase);
773 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
774 (void **)&tmp->passphrase,
775 &tmp->passphrase_len)) {
776 got_errno = SILC_CONFIG_ESILENT;
780 else if (!strcmp(name, "publickey")) {
781 CONFIG_IS_DOUBLE(tmp->publickeys);
782 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
783 (void **)&tmp->publickeys, NULL)) {
784 got_errno = SILC_CONFIG_ESILENT;
789 return SILC_CONFIG_EINTERNAL;
790 return SILC_CONFIG_OK;
793 silc_free(tmp->host);
794 silc_free(tmp->user);
795 silc_free(tmp->nick);
796 CONFIG_FREE_AUTH(tmp);
802 SILC_CONFIG_CALLBACK(fetch_deny)
804 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
806 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
807 type, name, context));
808 if (type == SILC_CONFIG_ARG_BLOCK) {
809 /* check the temporary struct's fields */
810 if (!tmp) /* discard empty sub-blocks */
811 return SILC_CONFIG_OK;
813 got_errno = SILC_CONFIG_EMISSFIELDS;
817 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
819 return SILC_CONFIG_OK;
821 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
823 /* Identify and save this value */
824 if (!strcmp(name, "host")) {
825 CONFIG_IS_DOUBLE(tmp->host);
826 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
828 else if (!strcmp(name, "reason")) {
829 CONFIG_IS_DOUBLE(tmp->reason);
830 tmp->reason = strdup((char *) val);
833 return SILC_CONFIG_EINTERNAL;
834 return SILC_CONFIG_OK;
837 silc_free(tmp->host);
838 silc_free(tmp->reason);
844 SILC_CONFIG_CALLBACK(fetch_server)
846 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
848 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
849 type, name, context));
850 if (type == SILC_CONFIG_ARG_BLOCK) {
851 /* check the temporary struct's fields */
852 if (!tmp) /* discard empty sub-blocks */
853 return SILC_CONFIG_OK;
855 /* the temporary struct is ok, append it to the list */
856 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
858 return SILC_CONFIG_OK;
860 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
862 /* Identify and save this value */
863 if (!strcmp(name, "host")) {
864 CONFIG_IS_DOUBLE(tmp->host);
865 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
867 else if (!strcmp(name, "passphrase")) {
868 CONFIG_IS_DOUBLE(tmp->passphrase);
869 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
870 (void **)&tmp->passphrase,
871 &tmp->passphrase_len)) {
872 got_errno = SILC_CONFIG_ESILENT;
876 else if (!strcmp(name, "publickey")) {
877 CONFIG_IS_DOUBLE(tmp->publickeys);
878 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
879 (void **)&tmp->publickeys, NULL)) {
880 got_errno = SILC_CONFIG_ESILENT;
884 else if (!strcmp(name, "params")) {
885 CONFIG_IS_DOUBLE(tmp->param);
886 tmp->param = my_find_param(config, (char *) val);
887 if (!tmp->param) { /* error message already output */
888 got_errno = SILC_CONFIG_EPRINTLINE;
892 else if (!strcmp(name, "backup")) {
893 tmp->backup_router = *(bool *)val;
896 return SILC_CONFIG_EINTERNAL;
898 return SILC_CONFIG_OK;
901 silc_free(tmp->host);
902 CONFIG_FREE_AUTH(tmp);
908 SILC_CONFIG_CALLBACK(fetch_router)
910 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
912 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
913 type, name, context));
914 if (type == SILC_CONFIG_ARG_BLOCK) {
915 if (!tmp) /* discard empty sub-blocks */
916 return SILC_CONFIG_OK;
918 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
920 return SILC_CONFIG_OK;
922 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
924 /* Identify and save this value */
925 if (!strcmp(name, "host")) {
926 CONFIG_IS_DOUBLE(tmp->host);
927 tmp->host = strdup((char *) val);
929 else if (!strcmp(name, "port")) {
930 int port = *(int *)val;
931 if ((port <= 0) || (port > 65535)) {
932 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
933 "Invalid port number!\n"));
934 got_errno = SILC_CONFIG_EPRINTLINE;
937 tmp->port = (SilcUInt16) port;
939 else if (!strcmp(name, "passphrase")) {
940 CONFIG_IS_DOUBLE(tmp->passphrase);
941 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
942 (void **)&tmp->passphrase,
943 &tmp->passphrase_len)) {
944 got_errno = SILC_CONFIG_ESILENT;
948 else if (!strcmp(name, "publickey")) {
949 CONFIG_IS_DOUBLE(tmp->publickeys);
950 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
951 (void **)&tmp->publickeys, NULL)) {
952 got_errno = SILC_CONFIG_ESILENT;
956 else if (!strcmp(name, "params")) {
957 CONFIG_IS_DOUBLE(tmp->param);
958 tmp->param = my_find_param(config, (char *) val);
959 if (!tmp->param) { /* error message already output */
960 got_errno = SILC_CONFIG_EPRINTLINE;
964 else if (!strcmp(name, "initiator")) {
965 tmp->initiator = *(bool *)val;
967 else if (!strcmp(name, "backuphost")) {
968 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
969 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
971 tmp->backup_router = TRUE;
973 else if (!strcmp(name, "backupport")) {
974 int port = *(int *)val;
975 if ((port <= 0) || (port > 65535)) {
976 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
977 "Invalid port number!\n"));
978 got_errno = SILC_CONFIG_EPRINTLINE;
981 tmp->backup_replace_port = (SilcUInt16) port;
983 else if (!strcmp(name, "backuplocal")) {
984 tmp->backup_local = *(bool *)val;
987 return SILC_CONFIG_EINTERNAL;
989 return SILC_CONFIG_OK;
992 silc_free(tmp->host);
993 silc_free(tmp->backup_replace_ip);
994 CONFIG_FREE_AUTH(tmp);
1000 /* known config options tables */
1001 static const SilcConfigTable table_general[] = {
1002 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1003 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1004 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1005 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1006 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1007 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1008 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1009 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1010 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1011 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1012 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1013 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1014 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1015 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1016 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1017 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1018 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1019 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1020 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1021 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1025 static const SilcConfigTable table_cipher[] = {
1026 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1027 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1028 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1029 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1033 static const SilcConfigTable table_hash[] = {
1034 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1035 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1036 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1037 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1041 static const SilcConfigTable table_hmac[] = {
1042 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1043 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1044 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1048 static const SilcConfigTable table_pkcs[] = {
1049 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1053 static const SilcConfigTable table_serverinfo_c[] = {
1054 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1055 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1059 static const SilcConfigTable table_serverinfo[] = {
1060 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1061 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1062 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1063 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1064 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1065 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1066 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1067 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1068 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1069 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1070 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1071 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1072 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1076 static const SilcConfigTable table_logging_c[] = {
1077 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1078 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1079 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1083 static const SilcConfigTable table_logging[] = {
1084 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1085 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1086 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1087 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1088 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1089 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1093 static const SilcConfigTable table_connparam[] = {
1094 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1095 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1096 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1097 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1098 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1099 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1100 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1101 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1102 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1103 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1104 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1105 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1106 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1107 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1111 static const SilcConfigTable table_client[] = {
1112 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1113 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1114 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1115 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1119 static const SilcConfigTable table_admin[] = {
1120 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1121 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1122 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1123 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1124 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1125 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1126 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1130 static const SilcConfigTable table_deny[] = {
1131 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1132 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1136 static const SilcConfigTable table_serverconn[] = {
1137 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1138 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1139 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1140 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1141 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1145 static const SilcConfigTable table_routerconn[] = {
1146 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1147 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1148 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1149 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1150 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1151 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1152 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1153 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1154 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1158 static const SilcConfigTable table_main[] = {
1159 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1160 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1161 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1162 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1163 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1164 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1165 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1166 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1167 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1168 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1169 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1170 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1171 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1175 /* Set default values to stuff that was not configured. */
1177 static void silc_server_config_set_defaults(SilcServerConfig config)
1179 my_set_param_defaults(&config->param, NULL);
1181 config->channel_rekey_secs = (config->channel_rekey_secs ?
1182 config->channel_rekey_secs :
1183 SILC_SERVER_CHANNEL_REKEY);
1184 config->key_exchange_timeout = (config->key_exchange_timeout ?
1185 config->key_exchange_timeout :
1186 SILC_SERVER_SKE_TIMEOUT);
1187 config->conn_auth_timeout = (config->conn_auth_timeout ?
1188 config->conn_auth_timeout :
1189 SILC_SERVER_CONNAUTH_TIMEOUT);
1192 /* Allocates a new configuration object, opens configuration file and
1193 parses it. The parsed data is returned to the newly allocated
1194 configuration object. The SilcServerConfig must be freed by calling
1195 the silc_server_config_destroy function. */
1197 SilcServerConfig silc_server_config_alloc(const char *filename)
1199 SilcServerConfig config_new;
1200 SilcConfigEntity ent;
1201 SilcConfigFile *file;
1203 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1205 /* alloc a config object */
1206 config_new = silc_calloc(1, sizeof(*config_new));
1207 config_new->refcount = 1;
1211 /* obtain a config file object */
1212 file = silc_config_open(filename);
1214 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1219 /* obtain a SilcConfig entity, we can use it to start the parsing */
1220 ent = silc_config_init(file);
1222 /* load the known configuration options, give our empty object as context */
1223 silc_config_register_table(ent, table_main, (void *) config_new);
1225 /* enter the main parsing loop. When this returns, we have the parsing
1226 * result and the object filled (or partially, in case of errors). */
1227 ret = silc_config_main(ent);
1228 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1229 silc_config_strerror(ret)));
1231 /* Check if the parser returned errors */
1233 /* handle this special error return which asks to quietly return */
1234 if (ret != SILC_CONFIG_ESILENT) {
1235 char *linebuf, *filename = silc_config_get_filename(file);
1236 SilcUInt32 line = silc_config_get_line(file);
1237 if (ret != SILC_CONFIG_EPRINTLINE)
1238 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1239 silc_config_strerror(ret)));
1240 linebuf = silc_config_read_line(file, line);
1241 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n\n", filename,
1245 silc_server_config_destroy(config_new);
1249 /* close (destroy) the file object */
1250 silc_config_close(file);
1252 /* If config_new is incomplete, abort the object and return NULL */
1253 if (!config_new->server_info) {
1254 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1255 "`server_info'\n"));
1256 silc_server_config_destroy(config_new);
1260 /* Set default to configuration parameters */
1261 silc_server_config_set_defaults(config_new);
1266 /* Increments the reference counter of a config object */
1268 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1273 ref->config = config;
1274 ref->ref_ptr = ref_ptr;
1275 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1276 config->refcount - 1, config->refcount));
1280 /* Decrements the reference counter of a config object. If the counter
1281 reaches 0, the config object is destroyed. */
1283 void silc_server_config_unref(SilcServerConfigRef *ref)
1286 silc_server_config_destroy(ref->config);
1289 /* Destroy a config object with all his children lists */
1291 void silc_server_config_destroy(SilcServerConfig config)
1296 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1297 config->refcount + 1, config->refcount));
1298 if (config->refcount > 0)
1301 SILC_LOG_DEBUG(("Freeing config context"));
1303 /* Destroy general config stuff */
1304 silc_free(config->module_path);
1305 silc_free(config->param.version_protocol);
1306 silc_free(config->param.version_software);
1307 silc_free(config->param.version_software_vendor);
1309 /* Destroy Logging channels */
1310 if (config->logging_info)
1311 silc_free(config->logging_info->file);
1312 if (config->logging_warnings)
1313 silc_free(config->logging_warnings->file);
1314 if (config->logging_errors)
1315 silc_free(config->logging_errors->file);
1316 if (config->logging_fatals)
1317 silc_free(config->logging_fatals->file);
1318 silc_free(config->logging_info);
1319 silc_free(config->logging_warnings);
1320 silc_free(config->logging_errors);
1321 silc_free(config->logging_fatals);
1323 /* Destroy the ServerInfo struct */
1324 if (config->server_info) {
1325 register SilcServerConfigServerInfo *si = config->server_info;
1326 silc_free(si->server_name);
1328 silc_free(si->primary->server_ip);
1329 silc_free(si->primary);
1331 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1333 silc_free(di->server_ip);
1336 silc_free(si->server_type);
1337 silc_free(si->location);
1338 silc_free(si->admin);
1339 silc_free(si->email);
1340 silc_free(si->user);
1341 silc_free(si->group);
1342 silc_free(si->motd_file);
1343 silc_free(si->pid_file);
1344 silc_pkcs_public_key_free(si->public_key);
1345 silc_pkcs_private_key_free(si->private_key);
1349 /* Now let's destroy the lists */
1351 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1353 silc_free(di->name);
1354 silc_free(di->module);
1357 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1358 silc_free(di->name);
1359 silc_free(di->module);
1362 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1363 silc_free(di->name);
1364 silc_free(di->hash);
1367 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1368 silc_free(di->name);
1371 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1372 config->conn_params)
1373 silc_free(di->name);
1374 silc_free(di->version_protocol);
1375 silc_free(di->version_software);
1376 silc_free(di->version_software_vendor);
1379 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1380 silc_free(di->host);
1381 CONFIG_FREE_AUTH(di);
1384 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1385 silc_free(di->host);
1386 silc_free(di->user);
1387 silc_free(di->nick);
1388 CONFIG_FREE_AUTH(di);
1391 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1392 silc_free(di->host);
1393 silc_free(di->reason);
1396 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1398 silc_free(di->host);
1399 CONFIG_FREE_AUTH(di);
1402 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1404 silc_free(di->host);
1405 silc_free(di->backup_replace_ip);
1406 CONFIG_FREE_AUTH(di);
1410 memset(config, 'F', sizeof(*config));
1414 /* Registers configured ciphers. These can then be allocated by the
1415 server when needed. */
1417 bool silc_server_config_register_ciphers(SilcServer server)
1419 SilcServerConfig config = server->config;
1420 SilcServerConfigCipher *cipher = config->cipher;
1421 char *module_path = config->module_path;
1423 SILC_LOG_DEBUG(("Registering configured ciphers"));
1425 if (!cipher) /* any cipher in the config file? */
1429 /* if there isn't a module_path OR there isn't a module sim name try to
1430 * use buil-in functions */
1431 if (!module_path || !cipher->module) {
1433 for (i = 0; silc_default_ciphers[i].name; i++)
1434 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1435 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1438 if (!silc_cipher_is_supported(cipher->name)) {
1439 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1440 silc_server_stop(server);
1445 /* Load (try at least) the crypto SIM module */
1446 char buf[1023], *alg_name;
1447 SilcCipherObject cipher_obj;
1450 memset(&cipher_obj, 0, sizeof(cipher_obj));
1451 cipher_obj.name = cipher->name;
1452 cipher_obj.block_len = cipher->block_length;
1453 cipher_obj.key_len = cipher->key_length * 8;
1455 /* build the libname */
1456 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1458 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1460 alg_name = strdup(cipher->name);
1461 if (strchr(alg_name, '-'))
1462 *strchr(alg_name, '-') = '\0';
1464 if (silc_sim_load(sim)) {
1465 cipher_obj.set_key =
1466 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1467 SILC_CIPHER_SIM_SET_KEY));
1468 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1469 cipher_obj.set_key_with_string =
1470 silc_sim_getsym(sim,
1471 silc_sim_symname(alg_name,
1472 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1473 SILC_LOG_DEBUG(("set_key_with_string=%p",
1474 cipher_obj.set_key_with_string));
1475 cipher_obj.encrypt =
1476 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1477 SILC_CIPHER_SIM_ENCRYPT_CBC));
1478 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1479 cipher_obj.decrypt =
1480 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1481 SILC_CIPHER_SIM_DECRYPT_CBC));
1482 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1483 cipher_obj.context_len =
1484 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1485 SILC_CIPHER_SIM_CONTEXT_LEN));
1486 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1488 /* Put the SIM to the list of all SIM's in server */
1489 silc_dlist_add(server->sim, sim);
1491 silc_free(alg_name);
1493 SILC_LOG_ERROR(("Error configuring ciphers"));
1494 silc_server_stop(server);
1498 /* Register the cipher */
1499 silc_cipher_register(&cipher_obj);
1501 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1502 "can't load modules!"));
1503 silc_server_stop(server);
1507 cipher = cipher->next;
1513 /* Registers configured hash functions. These can then be allocated by the
1514 server when needed. */
1516 bool silc_server_config_register_hashfuncs(SilcServer server)
1518 SilcServerConfig config = server->config;
1519 SilcServerConfigHash *hash = config->hash;
1520 char *module_path = config->module_path;
1522 SILC_LOG_DEBUG(("Registering configured hash functions"));
1524 if (!hash) /* any hash func in the config file? */
1528 /* if there isn't a module_path OR there isn't a module sim name try to
1529 * use buil-in functions */
1530 if (!module_path || !hash->module) {
1532 for (i = 0; silc_default_hash[i].name; i++)
1533 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1534 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1537 if (!silc_hash_is_supported(hash->name)) {
1538 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1539 silc_server_stop(server);
1544 /* Load (try at least) the hash SIM module */
1545 SilcHashObject hash_obj;
1548 memset(&hash_obj, 0, sizeof(hash_obj));
1549 hash_obj.name = hash->name;
1550 hash_obj.block_len = hash->block_length;
1551 hash_obj.hash_len = hash->digest_length;
1553 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1555 if ((silc_sim_load(sim))) {
1557 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1558 SILC_HASH_SIM_INIT));
1559 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1561 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1562 SILC_HASH_SIM_UPDATE));
1563 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1565 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1566 SILC_HASH_SIM_FINAL));
1567 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1568 hash_obj.context_len =
1569 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1570 SILC_HASH_SIM_CONTEXT_LEN));
1571 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1573 /* Put the SIM to the table of all SIM's in server */
1574 silc_dlist_add(server->sim, sim);
1576 SILC_LOG_ERROR(("Error configuring hash functions"));
1577 silc_server_stop(server);
1581 /* Register the hash function */
1582 silc_hash_register(&hash_obj);
1584 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1585 "can't load modules!"));
1586 silc_server_stop(server);
1596 /* Registers configure HMACs. These can then be allocated by the server
1599 bool silc_server_config_register_hmacs(SilcServer server)
1601 SilcServerConfig config = server->config;
1602 SilcServerConfigHmac *hmac = config->hmac;
1604 SILC_LOG_DEBUG(("Registering configured HMACs"));
1610 SilcHmacObject hmac_obj;
1611 if (!silc_hash_is_supported(hmac->hash)) {
1612 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1613 silc_server_stop(server);
1617 /* Register the HMAC */
1618 memset(&hmac_obj, 0, sizeof(hmac_obj));
1619 hmac_obj.name = hmac->name;
1620 hmac_obj.len = hmac->mac_length;
1621 silc_hmac_register(&hmac_obj);
1629 /* Registers configured PKCS's. */
1631 bool silc_server_config_register_pkcs(SilcServer server)
1633 SilcServerConfig config = server->config;
1634 SilcServerConfigPkcs *pkcs = config->pkcs;
1636 SILC_LOG_DEBUG(("Registering configured PKCS"));
1643 for (i = 0; silc_default_pkcs[i].name; i++)
1644 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1645 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1648 if (!silc_pkcs_is_supported(pkcs->name)) {
1649 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1650 silc_server_stop(server);
1659 /* Sets log files where log messages are saved by the server logger. */
1661 void silc_server_config_setlogfiles(SilcServer server)
1663 SilcServerConfig config = server->config;
1664 SilcServerConfigLogging *this;
1666 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1668 silc_log_quick = config->logging_quick;
1669 silc_log_flushdelay = (config->logging_flushdelay ?
1670 config->logging_flushdelay :
1671 SILC_SERVER_LOG_FLUSH_DELAY);
1673 if ((this = config->logging_fatals))
1674 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1676 if ((this = config->logging_errors))
1677 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1679 if ((this = config->logging_warnings))
1680 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1682 if ((this = config->logging_info))
1683 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1687 /* Returns client authentication information from configuration file by host
1690 SilcServerConfigClient *
1691 silc_server_config_find_client(SilcServer server, char *host)
1693 SilcServerConfig config = server->config;
1694 SilcServerConfigClient *client;
1696 if (!config || !host)
1699 for (client = config->clients; client; client = client->next) {
1700 if (client->host && !silc_string_compare(client->host, host))
1705 /* if none matched, then client is already NULL */
1709 /* Returns admin connection configuration by host, username and/or
1712 SilcServerConfigAdmin *
1713 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1716 SilcServerConfig config = server->config;
1717 SilcServerConfigAdmin *admin;
1719 /* make sure we have a value for the matching parameters */
1727 for (admin = config->admins; admin; admin = admin->next) {
1728 if (admin->host && !silc_string_compare(admin->host, host))
1730 if (admin->user && !silc_string_compare(admin->user, user))
1732 if (admin->nick && !silc_string_compare(admin->nick, nick))
1734 /* no checks failed -> this entry matches */
1738 /* if none matched, then admin is already NULL */
1742 /* Returns the denied connection configuration entry by host. */
1744 SilcServerConfigDeny *
1745 silc_server_config_find_denied(SilcServer server, char *host)
1747 SilcServerConfig config = server->config;
1748 SilcServerConfigDeny *deny;
1750 /* make sure we have a value for the matching parameters */
1751 if (!config || !host)
1754 for (deny = config->denied; deny; deny = deny->next) {
1755 if (deny->host && !silc_string_compare(deny->host, host))
1760 /* if none matched, then deny is already NULL */
1764 /* Returns server connection info from server configuartion by host
1767 SilcServerConfigServer *
1768 silc_server_config_find_server_conn(SilcServer server, char *host)
1770 SilcServerConfig config = server->config;
1771 SilcServerConfigServer *serv = NULL;
1776 if (!config->servers)
1779 for (serv = config->servers; serv; serv = serv->next) {
1780 if (!silc_string_compare(serv->host, host))
1788 /* Returns router connection info from server configuration by
1789 host (name or ip). */
1791 SilcServerConfigRouter *
1792 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1794 SilcServerConfig config = server->config;
1795 SilcServerConfigRouter *serv = NULL;
1800 if (!config->routers)
1803 for (serv = config->routers; serv; serv = serv->next) {
1804 if (!silc_string_compare(serv->host, host))
1806 if (port && serv->port && serv->port != port)
1814 /* Find backup router connection by host (name or ip) */
1816 SilcServerConfigRouter *
1817 silc_server_config_find_backup_conn(SilcServer server, char *host)
1819 SilcServerConfig config = server->config;
1820 SilcServerConfigRouter *serv = NULL;
1825 if (!config->routers)
1828 for (serv = config->routers; serv; serv = serv->next) {
1829 if (!serv->backup_router)
1831 if (!silc_string_compare(serv->host, host))
1839 /* Returns TRUE if configuration for a router connection that we are
1840 initiating exists. */
1842 bool silc_server_config_is_primary_route(SilcServer server)
1844 SilcServerConfig config = server->config;
1845 SilcServerConfigRouter *serv = NULL;
1849 serv = config->routers;
1850 for (i = 0; serv; i++) {
1851 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1862 /* Returns our primary connection configuration or NULL if we do not
1863 have primary router configured. */
1865 SilcServerConfigRouter *
1866 silc_server_config_get_primary_router(SilcServer server)
1868 SilcServerConfig config = server->config;
1869 SilcServerConfigRouter *serv = NULL;
1872 serv = config->routers;
1873 for (i = 0; serv; i++) {
1874 if (serv->initiator == TRUE && serv->backup_router == FALSE)
1882 /* If we have backup router configured that is going to replace us this
1883 function returns it. */
1885 SilcServerConfigRouter *
1886 silc_server_config_get_backup_router(SilcServer server)
1888 SilcServerConfig config = server->config;
1889 SilcServerConfigRouter *serv = NULL;
1892 if (server->server_type != SILC_ROUTER)
1895 serv = config->routers;
1896 for (i = 0; serv; i++) {
1897 if (serv->initiator == FALSE && serv->backup_router == TRUE &&
1898 serv->backup_local == TRUE &&
1899 !strcmp(server->config->server_info->primary->server_ip,
1900 serv->backup_replace_ip) &&
1901 server->config->server_info->primary->port ==
1902 serv->backup_replace_port)