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, "timestamp")) {
549 config->logging_timestamp = *(bool *)val;
551 else if (!strcmp(name, "quicklogs")) {
552 config->logging_quick = *(bool *)val;
554 else if (!strcmp(name, "flushdelay")) {
555 int flushdelay = *(int *)val;
556 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
557 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
558 "Invalid flushdelay value, use quicklogs if you "
559 "want real-time logging.\n"));
560 return SILC_CONFIG_EPRINTLINE;
562 config->logging_flushdelay = (long) flushdelay;
565 /* The following istances happens only in Logging's sub-blocks, a match
566 for the sub-block name means that you should store the filename/maxsize
567 temporary struct to the proper logging channel.
568 If we get a match for "file" or "maxsize" this means that we are inside
569 a sub-sub-block and it is safe to alloc a new tmp. */
570 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
571 else if (!strcmp(name, __chan__)) { \
572 if (!tmp) return SILC_CONFIG_OK; \
574 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
576 config->__member__ = tmp; \
577 config->tmp = NULL; \
579 FETCH_LOGGING_CHAN("info", logging_info)
580 FETCH_LOGGING_CHAN("warnings", logging_warnings)
581 FETCH_LOGGING_CHAN("errors", logging_errors)
582 FETCH_LOGGING_CHAN("fatals", logging_fatals)
583 #undef FETCH_LOGGING_CHAN
584 else if (!strcmp(name, "file")) {
585 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
586 CONFIG_IS_DOUBLE(tmp->file);
587 tmp->file = strdup((char *) val);
589 else if (!strcmp(name, "size")) {
591 config->tmp = silc_calloc(1, sizeof(*tmp));
592 tmp = (SilcServerConfigLogging *) config->tmp;
594 tmp->maxsize = *(SilcUInt32 *) val;
597 return SILC_CONFIG_EINTERNAL;
598 return SILC_CONFIG_OK;
601 silc_free(tmp->file);
607 SILC_CONFIG_CALLBACK(fetch_connparam)
609 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
611 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
612 type, name, context));
613 if (type == SILC_CONFIG_ARG_BLOCK) {
614 /* check the temporary struct's fields */
615 if (!tmp) /* discard empty sub-blocks */
616 return SILC_CONFIG_OK;
618 got_errno = SILC_CONFIG_EMISSFIELDS;
622 my_set_param_defaults(tmp, &config->param);
624 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
626 return SILC_CONFIG_OK;
628 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
630 if (!strcmp(name, "name")) {
631 CONFIG_IS_DOUBLE(tmp->name);
632 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
634 else if (!strcmp(name, "connections_max")) {
635 tmp->connections_max = *(SilcUInt32 *)val;
637 else if (!strcmp(name, "connections_max_per_host")) {
638 tmp->connections_max_per_host = *(SilcUInt32 *)val;
640 else if (!strcmp(name, "keepalive_secs")) {
641 tmp->keepalive_secs = *(SilcUInt32 *)val;
643 else if (!strcmp(name, "reconnect_count")) {
644 tmp->reconnect_count = *(SilcUInt32 *)val;
646 else if (!strcmp(name, "reconnect_interval")) {
647 tmp->reconnect_interval = *(SilcUInt32 *)val;
649 else if (!strcmp(name, "reconnect_interval_max")) {
650 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
652 else if (!strcmp(name, "reconnect_keep_trying")) {
653 tmp->reconnect_keep_trying = *(bool *)val;
655 else if (!strcmp(name, "key_exchange_rekey")) {
656 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
658 else if (!strcmp(name, "key_exchange_pfs")) {
659 tmp->key_exchange_pfs = *(bool *)val;
661 else if (!strcmp(name, "version_protocol")) {
662 CONFIG_IS_DOUBLE(tmp->version_protocol);
663 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
665 else if (!strcmp(name, "version_software")) {
666 CONFIG_IS_DOUBLE(tmp->version_software);
667 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
669 else if (!strcmp(name, "version_software_vendor")) {
670 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
671 tmp->version_software_vendor =
672 (*(char *)val ? strdup((char *) val) : NULL);
674 else if (!strcmp(name, "anonymous")) {
675 tmp->anonymous = *(bool *)val;
678 return SILC_CONFIG_EINTERNAL;
680 return SILC_CONFIG_OK;
683 silc_free(tmp->name);
689 SILC_CONFIG_CALLBACK(fetch_client)
691 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
693 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
694 type, name, context));
696 /* Alloc before block checking, because empty sub-blocks are welcome here */
697 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
699 if (type == SILC_CONFIG_ARG_BLOCK) {
700 /* empty sub-blocks are welcome */
701 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
703 return SILC_CONFIG_OK;
706 /* Identify and save this value */
707 if (!strcmp(name, "host")) {
708 CONFIG_IS_DOUBLE(tmp->host);
709 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
711 else if (!strcmp(name, "passphrase")) {
712 CONFIG_IS_DOUBLE(tmp->passphrase);
713 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
714 (void **)&tmp->passphrase,
715 &tmp->passphrase_len)) {
716 got_errno = SILC_CONFIG_ESILENT;
720 else if (!strcmp(name, "publickey")) {
721 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
722 (void **)&tmp->publickeys, NULL)) {
723 got_errno = SILC_CONFIG_ESILENT;
727 else if (!strcmp(name, "params")) {
728 CONFIG_IS_DOUBLE(tmp->param);
729 tmp->param = my_find_param(config, (char *) val);
730 if (!tmp->param) { /* error message already output */
731 got_errno = SILC_CONFIG_EPRINTLINE;
736 return SILC_CONFIG_EINTERNAL;
737 return SILC_CONFIG_OK;
740 silc_free(tmp->host);
741 CONFIG_FREE_AUTH(tmp);
747 SILC_CONFIG_CALLBACK(fetch_admin)
749 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
751 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
752 type, name, context));
753 if (type == SILC_CONFIG_ARG_BLOCK) {
754 /* check the temporary struct's fields */
755 if (!tmp) /* discard empty sub-blocks */
756 return SILC_CONFIG_OK;
758 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
760 return SILC_CONFIG_OK;
762 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
764 /* Identify and save this value */
765 if (!strcmp(name, "host")) {
766 CONFIG_IS_DOUBLE(tmp->host);
767 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
769 else if (!strcmp(name, "user")) {
770 CONFIG_IS_DOUBLE(tmp->user);
771 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
773 else if (!strcmp(name, "nick")) {
774 CONFIG_IS_DOUBLE(tmp->nick);
775 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
777 else if (!strcmp(name, "passphrase")) {
778 CONFIG_IS_DOUBLE(tmp->passphrase);
779 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
780 (void **)&tmp->passphrase,
781 &tmp->passphrase_len)) {
782 got_errno = SILC_CONFIG_ESILENT;
786 else if (!strcmp(name, "publickey")) {
787 CONFIG_IS_DOUBLE(tmp->publickeys);
788 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
789 (void **)&tmp->publickeys, NULL)) {
790 got_errno = SILC_CONFIG_ESILENT;
795 return SILC_CONFIG_EINTERNAL;
796 return SILC_CONFIG_OK;
799 silc_free(tmp->host);
800 silc_free(tmp->user);
801 silc_free(tmp->nick);
802 CONFIG_FREE_AUTH(tmp);
808 SILC_CONFIG_CALLBACK(fetch_deny)
810 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
812 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
813 type, name, context));
814 if (type == SILC_CONFIG_ARG_BLOCK) {
815 /* check the temporary struct's fields */
816 if (!tmp) /* discard empty sub-blocks */
817 return SILC_CONFIG_OK;
819 got_errno = SILC_CONFIG_EMISSFIELDS;
823 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
825 return SILC_CONFIG_OK;
827 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
829 /* Identify and save this value */
830 if (!strcmp(name, "host")) {
831 CONFIG_IS_DOUBLE(tmp->host);
832 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
834 else if (!strcmp(name, "reason")) {
835 CONFIG_IS_DOUBLE(tmp->reason);
836 tmp->reason = strdup((char *) val);
839 return SILC_CONFIG_EINTERNAL;
840 return SILC_CONFIG_OK;
843 silc_free(tmp->host);
844 silc_free(tmp->reason);
850 SILC_CONFIG_CALLBACK(fetch_server)
852 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
854 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
855 type, name, context));
856 if (type == SILC_CONFIG_ARG_BLOCK) {
857 /* check the temporary struct's fields */
858 if (!tmp) /* discard empty sub-blocks */
859 return SILC_CONFIG_OK;
861 /* the temporary struct is ok, append it to the list */
862 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
864 return SILC_CONFIG_OK;
866 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
868 /* Identify and save this value */
869 if (!strcmp(name, "host")) {
870 CONFIG_IS_DOUBLE(tmp->host);
871 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
873 else if (!strcmp(name, "passphrase")) {
874 CONFIG_IS_DOUBLE(tmp->passphrase);
875 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
876 (void **)&tmp->passphrase,
877 &tmp->passphrase_len)) {
878 got_errno = SILC_CONFIG_ESILENT;
882 else if (!strcmp(name, "publickey")) {
883 CONFIG_IS_DOUBLE(tmp->publickeys);
884 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
885 (void **)&tmp->publickeys, NULL)) {
886 got_errno = SILC_CONFIG_ESILENT;
890 else if (!strcmp(name, "params")) {
891 CONFIG_IS_DOUBLE(tmp->param);
892 tmp->param = my_find_param(config, (char *) val);
893 if (!tmp->param) { /* error message already output */
894 got_errno = SILC_CONFIG_EPRINTLINE;
898 else if (!strcmp(name, "backup")) {
899 tmp->backup_router = *(bool *)val;
902 return SILC_CONFIG_EINTERNAL;
904 return SILC_CONFIG_OK;
907 silc_free(tmp->host);
908 CONFIG_FREE_AUTH(tmp);
914 SILC_CONFIG_CALLBACK(fetch_router)
916 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
918 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
919 type, name, context));
920 if (type == SILC_CONFIG_ARG_BLOCK) {
921 if (!tmp) /* discard empty sub-blocks */
922 return SILC_CONFIG_OK;
924 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
926 return SILC_CONFIG_OK;
928 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
930 /* Identify and save this value */
931 if (!strcmp(name, "host")) {
932 CONFIG_IS_DOUBLE(tmp->host);
933 tmp->host = strdup((char *) val);
935 else if (!strcmp(name, "port")) {
936 int port = *(int *)val;
937 if ((port <= 0) || (port > 65535)) {
938 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
939 "Invalid port number!\n"));
940 got_errno = SILC_CONFIG_EPRINTLINE;
943 tmp->port = (SilcUInt16) port;
945 else if (!strcmp(name, "passphrase")) {
946 CONFIG_IS_DOUBLE(tmp->passphrase);
947 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
948 (void **)&tmp->passphrase,
949 &tmp->passphrase_len)) {
950 got_errno = SILC_CONFIG_ESILENT;
954 else if (!strcmp(name, "publickey")) {
955 CONFIG_IS_DOUBLE(tmp->publickeys);
956 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
957 (void **)&tmp->publickeys, NULL)) {
958 got_errno = SILC_CONFIG_ESILENT;
962 else if (!strcmp(name, "params")) {
963 CONFIG_IS_DOUBLE(tmp->param);
964 tmp->param = my_find_param(config, (char *) val);
965 if (!tmp->param) { /* error message already output */
966 got_errno = SILC_CONFIG_EPRINTLINE;
970 else if (!strcmp(name, "initiator")) {
971 tmp->initiator = *(bool *)val;
973 else if (!strcmp(name, "backuphost")) {
974 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
975 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
977 tmp->backup_router = TRUE;
979 else if (!strcmp(name, "backupport")) {
980 int port = *(int *)val;
981 if ((port <= 0) || (port > 65535)) {
982 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
983 "Invalid port number!\n"));
984 got_errno = SILC_CONFIG_EPRINTLINE;
987 tmp->backup_replace_port = (SilcUInt16) port;
989 else if (!strcmp(name, "backuplocal")) {
990 tmp->backup_local = *(bool *)val;
993 return SILC_CONFIG_EINTERNAL;
995 return SILC_CONFIG_OK;
998 silc_free(tmp->host);
999 silc_free(tmp->backup_replace_ip);
1000 CONFIG_FREE_AUTH(tmp);
1006 /* known config options tables */
1007 static const SilcConfigTable table_general[] = {
1008 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1009 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1010 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1011 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1012 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1013 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1014 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1015 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1016 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1017 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1018 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1019 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1020 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1021 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1022 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1023 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1024 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1025 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1026 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1027 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1031 static const SilcConfigTable table_cipher[] = {
1032 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1033 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1034 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1035 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1039 static const SilcConfigTable table_hash[] = {
1040 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1041 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1042 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1043 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1047 static const SilcConfigTable table_hmac[] = {
1048 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1049 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1050 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1054 static const SilcConfigTable table_pkcs[] = {
1055 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1059 static const SilcConfigTable table_serverinfo_c[] = {
1060 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1061 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1065 static const SilcConfigTable table_serverinfo[] = {
1066 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1067 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1068 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1069 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1070 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1071 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1072 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1073 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1074 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1075 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1076 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1077 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1078 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1082 static const SilcConfigTable table_logging_c[] = {
1083 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1084 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1085 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1089 static const SilcConfigTable table_logging[] = {
1090 { "timestamp", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1091 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1092 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1093 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1094 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1095 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1096 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1100 static const SilcConfigTable table_connparam[] = {
1101 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1102 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1103 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1104 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1105 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1106 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1107 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1108 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1109 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1110 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1111 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1112 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1113 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1114 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1115 { "anonymous", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1119 static const SilcConfigTable table_client[] = {
1120 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1121 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1122 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1123 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1127 static const SilcConfigTable table_admin[] = {
1128 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1129 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1130 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1131 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1132 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1133 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1134 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1138 static const SilcConfigTable table_deny[] = {
1139 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1140 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1144 static const SilcConfigTable table_serverconn[] = {
1145 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1146 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1147 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1148 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1149 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1153 static const SilcConfigTable table_routerconn[] = {
1154 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1155 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1156 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1157 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1158 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1159 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1160 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1161 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1162 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1166 static const SilcConfigTable table_main[] = {
1167 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1168 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1169 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1170 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1171 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1172 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1173 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1174 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1175 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1176 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1177 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1178 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1179 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1183 /* Set default values to stuff that was not configured. */
1185 static void silc_server_config_set_defaults(SilcServerConfig config)
1187 my_set_param_defaults(&config->param, NULL);
1189 config->channel_rekey_secs = (config->channel_rekey_secs ?
1190 config->channel_rekey_secs :
1191 SILC_SERVER_CHANNEL_REKEY);
1192 config->key_exchange_timeout = (config->key_exchange_timeout ?
1193 config->key_exchange_timeout :
1194 SILC_SERVER_SKE_TIMEOUT);
1195 config->conn_auth_timeout = (config->conn_auth_timeout ?
1196 config->conn_auth_timeout :
1197 SILC_SERVER_CONNAUTH_TIMEOUT);
1200 /* Allocates a new configuration object, opens configuration file and
1201 parses it. The parsed data is returned to the newly allocated
1202 configuration object. The SilcServerConfig must be freed by calling
1203 the silc_server_config_destroy function. */
1205 SilcServerConfig silc_server_config_alloc(const char *filename)
1207 SilcServerConfig config_new;
1208 SilcConfigEntity ent;
1209 SilcConfigFile *file;
1211 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1213 /* alloc a config object */
1214 config_new = silc_calloc(1, sizeof(*config_new));
1215 config_new->refcount = 1;
1219 /* general config defaults */
1220 config_new->logging_timestamp = TRUE;
1222 /* obtain a config file object */
1223 file = silc_config_open(filename);
1225 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1230 /* obtain a SilcConfig entity, we can use it to start the parsing */
1231 ent = silc_config_init(file);
1233 /* load the known configuration options, give our empty object as context */
1234 silc_config_register_table(ent, table_main, (void *) config_new);
1236 /* enter the main parsing loop. When this returns, we have the parsing
1237 * result and the object filled (or partially, in case of errors). */
1238 ret = silc_config_main(ent);
1239 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1240 silc_config_strerror(ret)));
1242 /* Check if the parser returned errors */
1244 /* handle this special error return which asks to quietly return */
1245 if (ret != SILC_CONFIG_ESILENT) {
1246 char *linebuf, *filename = silc_config_get_filename(file);
1247 SilcUInt32 line = silc_config_get_line(file);
1248 if (ret != SILC_CONFIG_EPRINTLINE)
1249 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1250 silc_config_strerror(ret)));
1251 linebuf = silc_config_read_line(file, line);
1252 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n\n", filename,
1256 silc_server_config_destroy(config_new);
1260 /* close (destroy) the file object */
1261 silc_config_close(file);
1263 /* If config_new is incomplete, abort the object and return NULL */
1264 if (!config_new->server_info) {
1265 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1266 "`server_info'\n"));
1267 silc_server_config_destroy(config_new);
1271 /* Set default to configuration parameters */
1272 silc_server_config_set_defaults(config_new);
1277 /* Increments the reference counter of a config object */
1279 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1284 ref->config = config;
1285 ref->ref_ptr = ref_ptr;
1286 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1287 config->refcount - 1, config->refcount));
1291 /* Decrements the reference counter of a config object. If the counter
1292 reaches 0, the config object is destroyed. */
1294 void silc_server_config_unref(SilcServerConfigRef *ref)
1297 silc_server_config_destroy(ref->config);
1300 /* Destroy a config object with all his children lists */
1302 void silc_server_config_destroy(SilcServerConfig config)
1307 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1308 config->refcount + 1, config->refcount));
1309 if (config->refcount > 0)
1312 SILC_LOG_DEBUG(("Freeing config context"));
1314 /* Destroy general config stuff */
1315 silc_free(config->module_path);
1316 silc_free(config->param.version_protocol);
1317 silc_free(config->param.version_software);
1318 silc_free(config->param.version_software_vendor);
1320 /* Destroy Logging channels */
1321 if (config->logging_info)
1322 silc_free(config->logging_info->file);
1323 if (config->logging_warnings)
1324 silc_free(config->logging_warnings->file);
1325 if (config->logging_errors)
1326 silc_free(config->logging_errors->file);
1327 if (config->logging_fatals)
1328 silc_free(config->logging_fatals->file);
1329 silc_free(config->logging_info);
1330 silc_free(config->logging_warnings);
1331 silc_free(config->logging_errors);
1332 silc_free(config->logging_fatals);
1334 /* Destroy the ServerInfo struct */
1335 if (config->server_info) {
1336 register SilcServerConfigServerInfo *si = config->server_info;
1337 silc_free(si->server_name);
1339 silc_free(si->primary->server_ip);
1340 silc_free(si->primary);
1342 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1344 silc_free(di->server_ip);
1347 silc_free(si->server_type);
1348 silc_free(si->location);
1349 silc_free(si->admin);
1350 silc_free(si->email);
1351 silc_free(si->user);
1352 silc_free(si->group);
1353 silc_free(si->motd_file);
1354 silc_free(si->pid_file);
1355 silc_pkcs_public_key_free(si->public_key);
1356 silc_pkcs_private_key_free(si->private_key);
1360 /* Now let's destroy the lists */
1362 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1364 silc_free(di->name);
1365 silc_free(di->module);
1368 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1369 silc_free(di->name);
1370 silc_free(di->module);
1373 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1374 silc_free(di->name);
1375 silc_free(di->hash);
1378 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1379 silc_free(di->name);
1382 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1383 config->conn_params)
1384 silc_free(di->name);
1385 silc_free(di->version_protocol);
1386 silc_free(di->version_software);
1387 silc_free(di->version_software_vendor);
1390 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1391 silc_free(di->host);
1392 CONFIG_FREE_AUTH(di);
1395 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1396 silc_free(di->host);
1397 silc_free(di->user);
1398 silc_free(di->nick);
1399 CONFIG_FREE_AUTH(di);
1402 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1403 silc_free(di->host);
1404 silc_free(di->reason);
1407 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1409 silc_free(di->host);
1410 CONFIG_FREE_AUTH(di);
1413 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1415 silc_free(di->host);
1416 silc_free(di->backup_replace_ip);
1417 CONFIG_FREE_AUTH(di);
1421 memset(config, 'F', sizeof(*config));
1425 /* Registers configured ciphers. These can then be allocated by the
1426 server when needed. */
1428 bool silc_server_config_register_ciphers(SilcServer server)
1430 SilcServerConfig config = server->config;
1431 SilcServerConfigCipher *cipher = config->cipher;
1432 char *module_path = config->module_path;
1434 SILC_LOG_DEBUG(("Registering configured ciphers"));
1436 if (!cipher) /* any cipher in the config file? */
1440 /* if there isn't a module_path OR there isn't a module sim name try to
1441 * use buil-in functions */
1442 if (!module_path || !cipher->module) {
1444 for (i = 0; silc_default_ciphers[i].name; i++)
1445 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1446 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1449 if (!silc_cipher_is_supported(cipher->name)) {
1450 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1451 silc_server_stop(server);
1456 /* Load (try at least) the crypto SIM module */
1457 char buf[1023], *alg_name;
1458 SilcCipherObject cipher_obj;
1461 memset(&cipher_obj, 0, sizeof(cipher_obj));
1462 cipher_obj.name = cipher->name;
1463 cipher_obj.block_len = cipher->block_length;
1464 cipher_obj.key_len = cipher->key_length * 8;
1466 /* build the libname */
1467 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1469 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1471 alg_name = strdup(cipher->name);
1472 if (strchr(alg_name, '-'))
1473 *strchr(alg_name, '-') = '\0';
1475 if (silc_sim_load(sim)) {
1476 cipher_obj.set_key =
1477 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1478 SILC_CIPHER_SIM_SET_KEY));
1479 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1480 cipher_obj.set_key_with_string =
1481 silc_sim_getsym(sim,
1482 silc_sim_symname(alg_name,
1483 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1484 SILC_LOG_DEBUG(("set_key_with_string=%p",
1485 cipher_obj.set_key_with_string));
1486 cipher_obj.encrypt =
1487 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1488 SILC_CIPHER_SIM_ENCRYPT_CBC));
1489 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1490 cipher_obj.decrypt =
1491 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1492 SILC_CIPHER_SIM_DECRYPT_CBC));
1493 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1494 cipher_obj.context_len =
1495 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1496 SILC_CIPHER_SIM_CONTEXT_LEN));
1497 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1499 /* Put the SIM to the list of all SIM's in server */
1500 silc_dlist_add(server->sim, sim);
1502 silc_free(alg_name);
1504 SILC_LOG_ERROR(("Error configuring ciphers"));
1505 silc_server_stop(server);
1509 /* Register the cipher */
1510 silc_cipher_register(&cipher_obj);
1512 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1513 "can't load modules!"));
1514 silc_server_stop(server);
1518 cipher = cipher->next;
1524 /* Registers configured hash functions. These can then be allocated by the
1525 server when needed. */
1527 bool silc_server_config_register_hashfuncs(SilcServer server)
1529 SilcServerConfig config = server->config;
1530 SilcServerConfigHash *hash = config->hash;
1531 char *module_path = config->module_path;
1533 SILC_LOG_DEBUG(("Registering configured hash functions"));
1535 if (!hash) /* any hash func in the config file? */
1539 /* if there isn't a module_path OR there isn't a module sim name try to
1540 * use buil-in functions */
1541 if (!module_path || !hash->module) {
1543 for (i = 0; silc_default_hash[i].name; i++)
1544 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1545 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1548 if (!silc_hash_is_supported(hash->name)) {
1549 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1550 silc_server_stop(server);
1555 /* Load (try at least) the hash SIM module */
1556 SilcHashObject hash_obj;
1559 memset(&hash_obj, 0, sizeof(hash_obj));
1560 hash_obj.name = hash->name;
1561 hash_obj.block_len = hash->block_length;
1562 hash_obj.hash_len = hash->digest_length;
1564 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1566 if ((silc_sim_load(sim))) {
1568 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1569 SILC_HASH_SIM_INIT));
1570 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1572 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1573 SILC_HASH_SIM_UPDATE));
1574 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1576 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1577 SILC_HASH_SIM_FINAL));
1578 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1579 hash_obj.context_len =
1580 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1581 SILC_HASH_SIM_CONTEXT_LEN));
1582 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1584 /* Put the SIM to the table of all SIM's in server */
1585 silc_dlist_add(server->sim, sim);
1587 SILC_LOG_ERROR(("Error configuring hash functions"));
1588 silc_server_stop(server);
1592 /* Register the hash function */
1593 silc_hash_register(&hash_obj);
1595 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1596 "can't load modules!"));
1597 silc_server_stop(server);
1607 /* Registers configure HMACs. These can then be allocated by the server
1610 bool silc_server_config_register_hmacs(SilcServer server)
1612 SilcServerConfig config = server->config;
1613 SilcServerConfigHmac *hmac = config->hmac;
1615 SILC_LOG_DEBUG(("Registering configured HMACs"));
1621 SilcHmacObject hmac_obj;
1622 if (!silc_hash_is_supported(hmac->hash)) {
1623 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1624 silc_server_stop(server);
1628 /* Register the HMAC */
1629 memset(&hmac_obj, 0, sizeof(hmac_obj));
1630 hmac_obj.name = hmac->name;
1631 hmac_obj.len = hmac->mac_length;
1632 silc_hmac_register(&hmac_obj);
1640 /* Registers configured PKCS's. */
1642 bool silc_server_config_register_pkcs(SilcServer server)
1644 SilcServerConfig config = server->config;
1645 SilcServerConfigPkcs *pkcs = config->pkcs;
1647 SILC_LOG_DEBUG(("Registering configured PKCS"));
1654 for (i = 0; silc_default_pkcs[i].name; i++)
1655 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1656 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1659 if (!silc_pkcs_is_supported(pkcs->name)) {
1660 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1661 silc_server_stop(server);
1670 /* Sets log files where log messages are saved by the server logger. */
1672 void silc_server_config_setlogfiles(SilcServer server)
1674 SilcServerConfig config = server->config;
1675 SilcServerConfigLogging *this;
1677 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1679 silc_log_timestamp = config->logging_timestamp;
1680 silc_log_quick = config->logging_quick;
1681 silc_log_flushdelay = (config->logging_flushdelay ?
1682 config->logging_flushdelay :
1683 SILC_SERVER_LOG_FLUSH_DELAY);
1685 if ((this = config->logging_fatals))
1686 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1688 if ((this = config->logging_errors))
1689 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1691 if ((this = config->logging_warnings))
1692 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1694 if ((this = config->logging_info))
1695 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1699 /* Returns client authentication information from configuration file by host
1702 SilcServerConfigClient *
1703 silc_server_config_find_client(SilcServer server, char *host)
1705 SilcServerConfig config = server->config;
1706 SilcServerConfigClient *client;
1708 if (!config || !host)
1711 for (client = config->clients; client; client = client->next) {
1712 if (client->host && !silc_string_compare(client->host, host))
1717 /* if none matched, then client is already NULL */
1721 /* Returns admin connection configuration by host, username and/or
1724 SilcServerConfigAdmin *
1725 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1728 SilcServerConfig config = server->config;
1729 SilcServerConfigAdmin *admin;
1731 /* make sure we have a value for the matching parameters */
1739 for (admin = config->admins; admin; admin = admin->next) {
1740 if (admin->host && !silc_string_compare(admin->host, host))
1742 if (admin->user && !silc_string_compare(admin->user, user))
1744 if (admin->nick && !silc_string_compare(admin->nick, nick))
1746 /* no checks failed -> this entry matches */
1750 /* if none matched, then admin is already NULL */
1754 /* Returns the denied connection configuration entry by host. */
1756 SilcServerConfigDeny *
1757 silc_server_config_find_denied(SilcServer server, char *host)
1759 SilcServerConfig config = server->config;
1760 SilcServerConfigDeny *deny;
1762 /* make sure we have a value for the matching parameters */
1763 if (!config || !host)
1766 for (deny = config->denied; deny; deny = deny->next) {
1767 if (deny->host && !silc_string_compare(deny->host, host))
1772 /* if none matched, then deny is already NULL */
1776 /* Returns server connection info from server configuartion by host
1779 SilcServerConfigServer *
1780 silc_server_config_find_server_conn(SilcServer server, char *host)
1782 SilcServerConfig config = server->config;
1783 SilcServerConfigServer *serv = NULL;
1788 if (!config->servers)
1791 for (serv = config->servers; serv; serv = serv->next) {
1792 if (!silc_string_compare(serv->host, host))
1800 /* Returns router connection info from server configuration by
1801 host (name or ip). */
1803 SilcServerConfigRouter *
1804 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1806 SilcServerConfig config = server->config;
1807 SilcServerConfigRouter *serv = NULL;
1812 if (!config->routers)
1815 for (serv = config->routers; serv; serv = serv->next) {
1816 if (!silc_string_compare(serv->host, host))
1818 if (port && serv->port && serv->port != port)
1826 /* Find backup router connection by host (name or ip) */
1828 SilcServerConfigRouter *
1829 silc_server_config_find_backup_conn(SilcServer server, char *host)
1831 SilcServerConfig config = server->config;
1832 SilcServerConfigRouter *serv = NULL;
1837 if (!config->routers)
1840 for (serv = config->routers; serv; serv = serv->next) {
1841 if (!serv->backup_router)
1843 if (!silc_string_compare(serv->host, host))
1851 /* Returns TRUE if configuration for a router connection that we are
1852 initiating exists. */
1854 bool silc_server_config_is_primary_route(SilcServer server)
1856 SilcServerConfig config = server->config;
1857 SilcServerConfigRouter *serv = NULL;
1861 serv = config->routers;
1862 for (i = 0; serv; i++) {
1863 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1874 /* Returns our primary connection configuration or NULL if we do not
1875 have primary router configured. */
1877 SilcServerConfigRouter *
1878 silc_server_config_get_primary_router(SilcServer server)
1880 SilcServerConfig config = server->config;
1881 SilcServerConfigRouter *serv = NULL;
1884 serv = config->routers;
1885 for (i = 0; serv; i++) {
1886 if (serv->initiator == TRUE && serv->backup_router == FALSE)
1894 /* If we have backup router configured that is going to replace us this
1895 function returns it. */
1897 SilcServerConfigRouter *
1898 silc_server_config_get_backup_router(SilcServer server)
1900 SilcServerConfig config = server->config;
1901 SilcServerConfigRouter *serv = NULL;
1904 if (server->server_type != SILC_ROUTER)
1907 serv = config->routers;
1908 for (i = 0; serv; i++) {
1909 if (serv->initiator == FALSE && serv->backup_router == TRUE &&
1910 serv->backup_local == TRUE &&
1911 !strcmp(server->config->server_info->primary->server_ip,
1912 serv->backup_replace_ip) &&
1913 server->config->server_info->primary->port ==
1914 serv->backup_replace_port)