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), 0);
126 *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
127 silc_utf8_encode(p, strlen(p), SILC_STRING_ASCII, *auth_data,
130 *auth_data = (void *) strdup(p);
131 *auth_data_len = (SilcUInt32) strlen(p);
134 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
135 /* p is a public key file name */
136 SilcPublicKey public_key;
138 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
139 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
140 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line "
141 "%lu: Could not load public key file!\n",
146 /* The auth_data is a pointer to the hash table of public keys. */
148 if (*auth_data == NULL)
149 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
151 my_free_public_key, NULL,
153 silc_hash_table_add(*auth_data, public_key, public_key);
156 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
157 "Unknown authentication method.\n", line));
165 SILC_CONFIG_CALLBACK(fetch_generic)
167 SilcServerConfig config = (SilcServerConfig) context;
170 if (!strcmp(name, "module_path")) {
171 CONFIG_IS_DOUBLE(config->module_path);
172 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
174 else if (!strcmp(name, "prefer_passphrase_auth")) {
175 config->prefer_passphrase_auth = *(bool *)val;
177 else if (!strcmp(name, "require_reverse_lookup")) {
178 config->require_reverse_lookup = *(bool *)val;
180 else if (!strcmp(name, "connections_max")) {
181 config->param.connections_max = (SilcUInt32) *(int *)val;
183 else if (!strcmp(name, "connections_max_per_host")) {
184 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
186 else if (!strcmp(name, "keepalive_secs")) {
187 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
189 else if (!strcmp(name, "reconnect_count")) {
190 config->param.reconnect_count = (SilcUInt32) *(int *)val;
192 else if (!strcmp(name, "reconnect_interval")) {
193 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
195 else if (!strcmp(name, "reconnect_interval_max")) {
196 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
198 else if (!strcmp(name, "reconnect_keep_trying")) {
199 config->param.reconnect_keep_trying = *(bool *)val;
201 else if (!strcmp(name, "key_exchange_rekey")) {
202 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
204 else if (!strcmp(name, "key_exchange_pfs")) {
205 config->param.key_exchange_pfs = *(bool *)val;
207 else if (!strcmp(name, "channel_rekey_secs")) {
208 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
210 else if (!strcmp(name, "key_exchange_timeout")) {
211 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
213 else if (!strcmp(name, "conn_auth_timeout")) {
214 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
216 else if (!strcmp(name, "version_protocol")) {
217 CONFIG_IS_DOUBLE(config->param.version_protocol);
218 config->param.version_protocol =
219 (*(char *)val ? strdup((char *) val) : NULL);
221 else if (!strcmp(name, "version_software")) {
222 CONFIG_IS_DOUBLE(config->param.version_software);
223 config->param.version_software =
224 (*(char *)val ? strdup((char *) val) : NULL);
226 else if (!strcmp(name, "version_software_vendor")) {
227 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
228 config->param.version_software_vendor =
229 (*(char *)val ? strdup((char *) val) : NULL);
231 else if (!strcmp(name, "detach_disabled")) {
232 config->detach_disabled = *(bool *)val;
234 else if (!strcmp(name, "detach_timeout")) {
235 config->detach_timeout = (SilcUInt32) *(int *)val;
238 return SILC_CONFIG_EINTERNAL;
240 return SILC_CONFIG_OK;
246 SILC_CONFIG_CALLBACK(fetch_cipher)
248 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
250 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
251 type, name, context));
252 if (type == SILC_CONFIG_ARG_BLOCK) {
253 /* check the temporary struct's fields */
254 if (!tmp) /* discard empty sub-blocks */
255 return SILC_CONFIG_OK;
257 got_errno = SILC_CONFIG_EMISSFIELDS;
261 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
263 return SILC_CONFIG_OK;
265 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
267 /* Identify and save this value */
268 if (!strcmp(name, "name")) {
269 CONFIG_IS_DOUBLE(tmp->name);
270 tmp->name = strdup((char *) val);
272 else if (!strcmp(name, "module")) {
273 CONFIG_IS_DOUBLE(tmp->module);
274 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
276 else if (!strcmp(name, "keylength")) {
277 tmp->key_length = *(SilcUInt32 *)val;
279 else if (!strcmp(name, "blocklength")) {
280 tmp->block_length = *(SilcUInt32 *)val;
283 return SILC_CONFIG_EINTERNAL;
284 return SILC_CONFIG_OK;
287 silc_free(tmp->name);
288 silc_free(tmp->module);
294 SILC_CONFIG_CALLBACK(fetch_hash)
296 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
298 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
299 type, name, context));
300 if (type == SILC_CONFIG_ARG_BLOCK) {
301 /* check the temporary struct's fields */
302 if (!tmp) /* discard empty sub-blocks */
303 return SILC_CONFIG_OK;
304 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
305 got_errno = SILC_CONFIG_EMISSFIELDS;
309 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
311 return SILC_CONFIG_OK;
313 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
315 /* Identify and save this value */
316 if (!strcmp(name, "name")) {
317 CONFIG_IS_DOUBLE(tmp->name);
318 tmp->name = strdup((char *) val);
320 else if (!strcmp(name, "module")) {
321 CONFIG_IS_DOUBLE(tmp->module);
322 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
324 else if (!strcmp(name, "blocklength")) {
325 tmp->block_length = *(int *)val;
327 else if (!strcmp(name, "digestlength")) {
328 tmp->digest_length = *(int *)val;
331 return SILC_CONFIG_EINTERNAL;
332 return SILC_CONFIG_OK;
335 silc_free(tmp->name);
336 silc_free(tmp->module);
342 SILC_CONFIG_CALLBACK(fetch_hmac)
344 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
346 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
347 type, name, context));
348 if (type == SILC_CONFIG_ARG_BLOCK) {
349 /* check the temporary struct's fields */
350 if (!tmp) /* discard empty sub-blocks */
351 return SILC_CONFIG_OK;
352 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
353 got_errno = SILC_CONFIG_EMISSFIELDS;
357 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
359 return SILC_CONFIG_OK;
361 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
363 /* Identify and save this value */
364 if (!strcmp(name, "name")) {
365 CONFIG_IS_DOUBLE(tmp->name);
366 tmp->name = strdup((char *) val);
368 else if (!strcmp(name, "hash")) {
369 CONFIG_IS_DOUBLE(tmp->hash);
370 tmp->hash = strdup((char *) val);
372 else if (!strcmp(name, "maclength")) {
373 tmp->mac_length = *(int *)val;
376 return SILC_CONFIG_EINTERNAL;
377 return SILC_CONFIG_OK;
380 silc_free(tmp->name);
381 silc_free(tmp->hash);
387 SILC_CONFIG_CALLBACK(fetch_pkcs)
389 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
391 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
392 type, name, context));
393 if (type == SILC_CONFIG_ARG_BLOCK) {
394 /* check the temporary struct's fields */
395 if (!tmp) /* discard empty sub-blocks */
396 return SILC_CONFIG_OK;
398 got_errno = SILC_CONFIG_EMISSFIELDS;
402 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
404 return SILC_CONFIG_OK;
406 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
408 /* Identify and save this value */
409 if (!strcmp(name, "name")) {
410 CONFIG_IS_DOUBLE(tmp->name);
411 tmp->name = strdup((char *) val);
414 return SILC_CONFIG_EINTERNAL;
415 return SILC_CONFIG_OK;
418 silc_free(tmp->name);
424 SILC_CONFIG_CALLBACK(fetch_serverinfo)
426 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
427 SilcServerConfigServerInfo *server_info = config->server_info;
429 /* if there isn't the struct alloc it */
431 config->server_info = server_info = (SilcServerConfigServerInfo *)
432 silc_calloc(1, sizeof(*server_info));
434 if (type == SILC_CONFIG_ARG_BLOCK) {
435 if (!strcmp(name, "primary")) {
436 CONFIG_IS_DOUBLE(server_info->primary);
438 return SILC_CONFIG_OK;
439 server_info->primary = tmp;
441 return SILC_CONFIG_OK;
442 } else if (!strcmp(name, "secondary")) {
444 return SILC_CONFIG_OK;
445 SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
447 return SILC_CONFIG_OK;
448 } else if (!server_info->public_key || !server_info->private_key) {
449 got_errno = SILC_CONFIG_EMISSFIELDS;
452 return SILC_CONFIG_OK;
454 if (!strcmp(name, "hostname")) {
455 CONFIG_IS_DOUBLE(server_info->server_name);
456 server_info->server_name = strdup((char *) val);
458 else if (!strcmp(name, "ip")) {
459 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
460 CONFIG_IS_DOUBLE(tmp->server_ip);
461 tmp->server_ip = strdup((char *) val);
463 else if (!strcmp(name, "port")) {
464 int port = *(int *)val;
465 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
466 if ((port <= 0) || (port > 65535)) {
467 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
468 "Invalid port number!\n"));
469 got_errno = SILC_CONFIG_EPRINTLINE;
472 tmp->port = (SilcUInt16) port;
474 else if (!strcmp(name, "servertype")) {
475 CONFIG_IS_DOUBLE(server_info->server_type);
476 server_info->server_type = strdup((char *) val);
478 else if (!strcmp(name, "admin")) {
479 CONFIG_IS_DOUBLE(server_info->admin);
480 server_info->admin = strdup((char *) val);
482 else if (!strcmp(name, "adminemail")) {
483 CONFIG_IS_DOUBLE(server_info->email);
484 server_info->email = strdup((char *) val);
486 else if (!strcmp(name, "location")) {
487 CONFIG_IS_DOUBLE(server_info->location);
488 server_info->location = strdup((char *) val);
490 else if (!strcmp(name, "user")) {
491 CONFIG_IS_DOUBLE(server_info->user);
492 server_info->user = strdup((char *) val);
494 else if (!strcmp(name, "group")) {
495 CONFIG_IS_DOUBLE(server_info->group);
496 server_info->group = strdup((char *) val);
498 else if (!strcmp(name, "motdfile")) {
499 CONFIG_IS_DOUBLE(server_info->motd_file);
500 server_info->motd_file = strdup((char *) val);
502 else if (!strcmp(name, "pidfile")) {
503 CONFIG_IS_DOUBLE(server_info->pid_file);
504 server_info->pid_file = strdup((char *) val);
506 else if (!strcmp(name, "publickey")) {
507 char *file_tmp = (char *) val;
509 /* try to load specified file, if fail stop config parsing */
510 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
512 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
513 SILC_PKCS_FILE_BIN)) {
514 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n"));
515 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
516 return SILC_CONFIG_ESILENT;
519 else if (!strcmp(name, "privatekey")) {
520 char *file_tmp = (char *) val;
522 /* try to load specified file, if fail stop config parsing */
523 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
525 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
526 SILC_PKCS_FILE_PEM)) {
527 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n"));
528 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
529 return SILC_CONFIG_ESILENT;
533 return SILC_CONFIG_EINTERNAL;
534 return SILC_CONFIG_OK;
538 silc_free(config->tmp);
543 SILC_CONFIG_CALLBACK(fetch_logging)
545 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
547 if (!strcmp(name, "quicklogs")) {
548 config->logging_quick = *(bool *)val;
550 else if (!strcmp(name, "flushdelay")) {
551 int flushdelay = *(int *)val;
552 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
553 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
554 "Invalid flushdelay value, use quicklogs if you "
555 "want real-time logging.\n"));
556 return SILC_CONFIG_EPRINTLINE;
558 config->logging_flushdelay = (long) flushdelay;
561 /* The following istances happens only in Logging's sub-blocks, a match
562 for the sub-block name means that you should store the filename/maxsize
563 temporary struct to the proper logging channel.
564 If we get a match for "file" or "maxsize" this means that we are inside
565 a sub-sub-block and it is safe to alloc a new tmp. */
566 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
567 else if (!strcmp(name, __chan__)) { \
568 if (!tmp) return SILC_CONFIG_OK; \
570 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
572 config->__member__ = tmp; \
573 config->tmp = NULL; \
575 FETCH_LOGGING_CHAN("info", logging_info)
576 FETCH_LOGGING_CHAN("warnings", logging_warnings)
577 FETCH_LOGGING_CHAN("errors", logging_errors)
578 FETCH_LOGGING_CHAN("fatals", logging_fatals)
579 #undef FETCH_LOGGING_CHAN
580 else if (!strcmp(name, "file")) {
581 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
582 CONFIG_IS_DOUBLE(tmp->file);
583 tmp->file = strdup((char *) val);
585 else if (!strcmp(name, "size")) {
587 config->tmp = silc_calloc(1, sizeof(*tmp));
588 tmp = (SilcServerConfigLogging *) config->tmp;
590 tmp->maxsize = *(SilcUInt32 *) val;
593 return SILC_CONFIG_EINTERNAL;
594 return SILC_CONFIG_OK;
597 silc_free(tmp->file);
603 SILC_CONFIG_CALLBACK(fetch_connparam)
605 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
607 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
608 type, name, context));
609 if (type == SILC_CONFIG_ARG_BLOCK) {
610 /* check the temporary struct's fields */
611 if (!tmp) /* discard empty sub-blocks */
612 return SILC_CONFIG_OK;
614 got_errno = SILC_CONFIG_EMISSFIELDS;
618 my_set_param_defaults(tmp, &config->param);
620 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
622 return SILC_CONFIG_OK;
624 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
626 if (!strcmp(name, "name")) {
627 CONFIG_IS_DOUBLE(tmp->name);
628 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
630 else if (!strcmp(name, "connections_max")) {
631 tmp->connections_max = *(SilcUInt32 *)val;
633 else if (!strcmp(name, "connections_max_per_host")) {
634 tmp->connections_max_per_host = *(SilcUInt32 *)val;
636 else if (!strcmp(name, "keepalive_secs")) {
637 tmp->keepalive_secs = *(SilcUInt32 *)val;
639 else if (!strcmp(name, "reconnect_count")) {
640 tmp->reconnect_count = *(SilcUInt32 *)val;
642 else if (!strcmp(name, "reconnect_interval")) {
643 tmp->reconnect_interval = *(SilcUInt32 *)val;
645 else if (!strcmp(name, "reconnect_interval_max")) {
646 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
648 else if (!strcmp(name, "reconnect_keep_trying")) {
649 tmp->reconnect_keep_trying = *(bool *)val;
651 else if (!strcmp(name, "key_exchange_rekey")) {
652 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
654 else if (!strcmp(name, "key_exchange_pfs")) {
655 tmp->key_exchange_pfs = *(bool *)val;
657 else if (!strcmp(name, "version_protocol")) {
658 CONFIG_IS_DOUBLE(tmp->version_protocol);
659 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
661 else if (!strcmp(name, "version_software")) {
662 CONFIG_IS_DOUBLE(tmp->version_software);
663 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
665 else if (!strcmp(name, "version_software_vendor")) {
666 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
667 tmp->version_software_vendor =
668 (*(char *)val ? strdup((char *) val) : NULL);
671 return SILC_CONFIG_EINTERNAL;
673 return SILC_CONFIG_OK;
676 silc_free(tmp->name);
682 SILC_CONFIG_CALLBACK(fetch_client)
684 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
686 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
687 type, name, context));
689 /* Alloc before block checking, because empty sub-blocks are welcome here */
690 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
692 if (type == SILC_CONFIG_ARG_BLOCK) {
693 /* empty sub-blocks are welcome */
694 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
696 return SILC_CONFIG_OK;
699 /* Identify and save this value */
700 if (!strcmp(name, "host")) {
701 CONFIG_IS_DOUBLE(tmp->host);
702 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
704 else if (!strcmp(name, "passphrase")) {
705 CONFIG_IS_DOUBLE(tmp->passphrase);
706 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
707 (void **)&tmp->passphrase,
708 &tmp->passphrase_len)) {
709 got_errno = SILC_CONFIG_ESILENT;
713 else if (!strcmp(name, "publickey")) {
714 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
715 (void **)&tmp->publickeys, NULL)) {
716 got_errno = SILC_CONFIG_ESILENT;
720 else if (!strcmp(name, "params")) {
721 CONFIG_IS_DOUBLE(tmp->param);
722 tmp->param = my_find_param(config, (char *) val);
723 if (!tmp->param) { /* error message already output */
724 got_errno = SILC_CONFIG_EPRINTLINE;
729 return SILC_CONFIG_EINTERNAL;
730 return SILC_CONFIG_OK;
733 silc_free(tmp->host);
734 CONFIG_FREE_AUTH(tmp);
740 SILC_CONFIG_CALLBACK(fetch_admin)
742 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
744 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
745 type, name, context));
746 if (type == SILC_CONFIG_ARG_BLOCK) {
747 /* check the temporary struct's fields */
748 if (!tmp) /* discard empty sub-blocks */
749 return SILC_CONFIG_OK;
751 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
753 return SILC_CONFIG_OK;
755 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
757 /* Identify and save this value */
758 if (!strcmp(name, "host")) {
759 CONFIG_IS_DOUBLE(tmp->host);
760 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
762 else if (!strcmp(name, "user")) {
763 CONFIG_IS_DOUBLE(tmp->user);
764 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
766 else if (!strcmp(name, "nick")) {
767 CONFIG_IS_DOUBLE(tmp->nick);
768 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
770 else if (!strcmp(name, "passphrase")) {
771 CONFIG_IS_DOUBLE(tmp->passphrase);
772 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
773 (void **)&tmp->passphrase,
774 &tmp->passphrase_len)) {
775 got_errno = SILC_CONFIG_ESILENT;
779 else if (!strcmp(name, "publickey")) {
780 CONFIG_IS_DOUBLE(tmp->publickeys);
781 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
782 (void **)&tmp->publickeys, NULL)) {
783 got_errno = SILC_CONFIG_ESILENT;
788 return SILC_CONFIG_EINTERNAL;
789 return SILC_CONFIG_OK;
792 silc_free(tmp->host);
793 silc_free(tmp->user);
794 silc_free(tmp->nick);
795 CONFIG_FREE_AUTH(tmp);
801 SILC_CONFIG_CALLBACK(fetch_deny)
803 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
805 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
806 type, name, context));
807 if (type == SILC_CONFIG_ARG_BLOCK) {
808 /* check the temporary struct's fields */
809 if (!tmp) /* discard empty sub-blocks */
810 return SILC_CONFIG_OK;
812 got_errno = SILC_CONFIG_EMISSFIELDS;
816 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
818 return SILC_CONFIG_OK;
820 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
822 /* Identify and save this value */
823 if (!strcmp(name, "host")) {
824 CONFIG_IS_DOUBLE(tmp->host);
825 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
827 else if (!strcmp(name, "reason")) {
828 CONFIG_IS_DOUBLE(tmp->reason);
829 tmp->reason = strdup((char *) val);
832 return SILC_CONFIG_EINTERNAL;
833 return SILC_CONFIG_OK;
836 silc_free(tmp->host);
837 silc_free(tmp->reason);
843 SILC_CONFIG_CALLBACK(fetch_server)
845 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
847 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
848 type, name, context));
849 if (type == SILC_CONFIG_ARG_BLOCK) {
850 /* check the temporary struct's fields */
851 if (!tmp) /* discard empty sub-blocks */
852 return SILC_CONFIG_OK;
854 /* the temporary struct is ok, append it to the list */
855 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
857 return SILC_CONFIG_OK;
859 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
861 /* Identify and save this value */
862 if (!strcmp(name, "host")) {
863 CONFIG_IS_DOUBLE(tmp->host);
864 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
866 else if (!strcmp(name, "passphrase")) {
867 CONFIG_IS_DOUBLE(tmp->passphrase);
868 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
869 (void **)&tmp->passphrase,
870 &tmp->passphrase_len)) {
871 got_errno = SILC_CONFIG_ESILENT;
875 else if (!strcmp(name, "publickey")) {
876 CONFIG_IS_DOUBLE(tmp->publickeys);
877 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
878 (void **)&tmp->publickeys, NULL)) {
879 got_errno = SILC_CONFIG_ESILENT;
883 else if (!strcmp(name, "params")) {
884 CONFIG_IS_DOUBLE(tmp->param);
885 tmp->param = my_find_param(config, (char *) val);
886 if (!tmp->param) { /* error message already output */
887 got_errno = SILC_CONFIG_EPRINTLINE;
891 else if (!strcmp(name, "backup")) {
892 tmp->backup_router = *(bool *)val;
895 return SILC_CONFIG_EINTERNAL;
897 return SILC_CONFIG_OK;
900 silc_free(tmp->host);
901 CONFIG_FREE_AUTH(tmp);
907 SILC_CONFIG_CALLBACK(fetch_router)
909 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
911 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
912 type, name, context));
913 if (type == SILC_CONFIG_ARG_BLOCK) {
914 if (!tmp) /* discard empty sub-blocks */
915 return SILC_CONFIG_OK;
917 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
919 return SILC_CONFIG_OK;
921 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
923 /* Identify and save this value */
924 if (!strcmp(name, "host")) {
925 CONFIG_IS_DOUBLE(tmp->host);
926 tmp->host = strdup((char *) val);
928 else if (!strcmp(name, "port")) {
929 int port = *(int *)val;
930 if ((port <= 0) || (port > 65535)) {
931 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
932 "Invalid port number!\n"));
933 got_errno = SILC_CONFIG_EPRINTLINE;
936 tmp->port = (SilcUInt16) port;
938 else if (!strcmp(name, "passphrase")) {
939 CONFIG_IS_DOUBLE(tmp->passphrase);
940 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
941 (void **)&tmp->passphrase,
942 &tmp->passphrase_len)) {
943 got_errno = SILC_CONFIG_ESILENT;
947 else if (!strcmp(name, "publickey")) {
948 CONFIG_IS_DOUBLE(tmp->publickeys);
949 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
950 (void **)&tmp->publickeys, NULL)) {
951 got_errno = SILC_CONFIG_ESILENT;
955 else if (!strcmp(name, "params")) {
956 CONFIG_IS_DOUBLE(tmp->param);
957 tmp->param = my_find_param(config, (char *) val);
958 if (!tmp->param) { /* error message already output */
959 got_errno = SILC_CONFIG_EPRINTLINE;
963 else if (!strcmp(name, "initiator")) {
964 tmp->initiator = *(bool *)val;
966 else if (!strcmp(name, "backuphost")) {
967 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
968 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
971 else if (!strcmp(name, "backupport")) {
972 int port = *(int *)val;
973 if ((port <= 0) || (port > 65535)) {
974 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
975 "Invalid port number!\n"));
976 got_errno = SILC_CONFIG_EPRINTLINE;
979 tmp->backup_replace_port = (SilcUInt16) port;
981 else if (!strcmp(name, "backuplocal")) {
982 tmp->backup_local = *(bool *)val;
985 return SILC_CONFIG_EINTERNAL;
987 return SILC_CONFIG_OK;
990 silc_free(tmp->host);
991 silc_free(tmp->backup_replace_ip);
992 CONFIG_FREE_AUTH(tmp);
998 /* known config options tables */
999 static const SilcConfigTable table_general[] = {
1000 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1001 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1002 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1003 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1004 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1005 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1006 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1007 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1008 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1009 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1010 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1011 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1012 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1013 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1014 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1015 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1016 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1017 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1018 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1019 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1023 static const SilcConfigTable table_cipher[] = {
1024 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1025 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1026 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1027 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1031 static const SilcConfigTable table_hash[] = {
1032 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1033 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1034 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1035 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1039 static const SilcConfigTable table_hmac[] = {
1040 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1041 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1042 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1046 static const SilcConfigTable table_pkcs[] = {
1047 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1051 static const SilcConfigTable table_serverinfo_c[] = {
1052 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1053 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1057 static const SilcConfigTable table_serverinfo[] = {
1058 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1059 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1060 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1061 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1062 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1063 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1064 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1065 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1066 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1067 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1068 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1069 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1070 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1074 static const SilcConfigTable table_logging_c[] = {
1075 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1076 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1077 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1081 static const SilcConfigTable table_logging[] = {
1082 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1083 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1084 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1085 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1086 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1087 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1091 static const SilcConfigTable table_connparam[] = {
1092 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1093 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1094 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1095 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1096 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1097 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1098 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1099 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1100 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1101 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1102 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1103 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1104 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1105 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1109 static const SilcConfigTable table_client[] = {
1110 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1111 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1112 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1113 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1117 static const SilcConfigTable table_admin[] = {
1118 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1119 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1120 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1121 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1122 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1123 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1124 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1128 static const SilcConfigTable table_deny[] = {
1129 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1130 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1134 static const SilcConfigTable table_serverconn[] = {
1135 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1136 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1137 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1138 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1139 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1143 static const SilcConfigTable table_routerconn[] = {
1144 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1145 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1146 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1147 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1148 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1149 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1150 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1151 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1152 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1156 static const SilcConfigTable table_main[] = {
1157 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1158 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1159 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1160 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1161 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1162 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1163 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1164 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1165 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1166 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1167 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1168 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1169 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1173 /* Set default values to stuff that was not configured. */
1175 static void silc_server_config_set_defaults(SilcServerConfig config)
1177 my_set_param_defaults(&config->param, NULL);
1179 config->channel_rekey_secs = (config->channel_rekey_secs ?
1180 config->channel_rekey_secs :
1181 SILC_SERVER_CHANNEL_REKEY);
1182 config->key_exchange_timeout = (config->key_exchange_timeout ?
1183 config->key_exchange_timeout :
1184 SILC_SERVER_SKE_TIMEOUT);
1185 config->conn_auth_timeout = (config->conn_auth_timeout ?
1186 config->conn_auth_timeout :
1187 SILC_SERVER_CONNAUTH_TIMEOUT);
1190 /* Allocates a new configuration object, opens configuration file and
1191 parses it. The parsed data is returned to the newly allocated
1192 configuration object. The SilcServerConfig must be freed by calling
1193 the silc_server_config_destroy function. */
1195 SilcServerConfig silc_server_config_alloc(const char *filename)
1197 SilcServerConfig config_new;
1198 SilcConfigEntity ent;
1199 SilcConfigFile *file;
1201 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1203 /* alloc a config object */
1204 config_new = silc_calloc(1, sizeof(*config_new));
1205 config_new->refcount = 1;
1209 /* obtain a config file object */
1210 file = silc_config_open(filename);
1212 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1217 /* obtain a SilcConfig entity, we can use it to start the parsing */
1218 ent = silc_config_init(file);
1220 /* load the known configuration options, give our empty object as context */
1221 silc_config_register_table(ent, table_main, (void *) config_new);
1223 /* enter the main parsing loop. When this returns, we have the parsing
1224 * result and the object filled (or partially, in case of errors). */
1225 ret = silc_config_main(ent);
1226 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1227 silc_config_strerror(ret)));
1229 /* Check if the parser returned errors */
1231 /* handle this special error return which asks to quietly return */
1232 if (ret != SILC_CONFIG_ESILENT) {
1233 char *linebuf, *filename = silc_config_get_filename(file);
1234 SilcUInt32 line = silc_config_get_line(file);
1235 if (ret != SILC_CONFIG_EPRINTLINE)
1236 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1237 silc_config_strerror(ret)));
1238 linebuf = silc_config_read_line(file, line);
1239 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n\n", filename,
1243 silc_server_config_destroy(config_new);
1247 /* close (destroy) the file object */
1248 silc_config_close(file);
1250 /* If config_new is incomplete, abort the object and return NULL */
1251 if (!config_new->server_info) {
1252 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1253 "`server_info'\n"));
1254 silc_server_config_destroy(config_new);
1258 /* XXX are there any other mandatory sections in the config file? */
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);
1319 /* Destroy the ServerInfo struct */
1320 if (config->server_info) {
1321 register SilcServerConfigServerInfo *si = config->server_info;
1322 silc_free(si->server_name);
1324 silc_free(si->primary->server_ip);
1325 silc_free(si->primary);
1327 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1329 silc_free(di->server_ip);
1332 silc_free(si->server_type);
1333 silc_free(si->location);
1334 silc_free(si->admin);
1335 silc_free(si->email);
1336 silc_free(si->user);
1337 silc_free(si->group);
1338 silc_free(si->motd_file);
1339 silc_free(si->pid_file);
1340 silc_pkcs_public_key_free(si->public_key);
1341 silc_pkcs_private_key_free(si->private_key);
1344 /* Now let's destroy the lists */
1346 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1348 silc_free(di->name);
1349 silc_free(di->module);
1352 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1353 silc_free(di->name);
1354 silc_free(di->module);
1357 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1358 silc_free(di->name);
1359 silc_free(di->hash);
1362 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1363 silc_free(di->name);
1366 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1367 config->conn_params)
1368 silc_free(di->name);
1369 silc_free(di->version_protocol);
1370 silc_free(di->version_software);
1371 silc_free(di->version_software_vendor);
1374 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1375 silc_free(di->host);
1376 CONFIG_FREE_AUTH(di);
1379 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1380 silc_free(di->host);
1381 silc_free(di->user);
1382 silc_free(di->nick);
1383 CONFIG_FREE_AUTH(di);
1386 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1387 silc_free(di->host);
1388 silc_free(di->reason);
1391 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1393 silc_free(di->host);
1394 CONFIG_FREE_AUTH(di);
1397 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1399 silc_free(di->host);
1400 silc_free(di->backup_replace_ip);
1401 CONFIG_FREE_AUTH(di);
1405 memset(config, 'F', sizeof(*config));
1409 /* Registers configured ciphers. These can then be allocated by the
1410 server when needed. */
1412 bool silc_server_config_register_ciphers(SilcServer server)
1414 SilcServerConfig config = server->config;
1415 SilcServerConfigCipher *cipher = config->cipher;
1416 char *module_path = config->module_path;
1418 SILC_LOG_DEBUG(("Registering configured ciphers"));
1420 if (!cipher) /* any cipher in the config file? */
1424 /* if there isn't a module_path OR there isn't a module sim name try to
1425 * use buil-in functions */
1426 if (!module_path || !cipher->module) {
1428 for (i = 0; silc_default_ciphers[i].name; i++)
1429 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1430 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1433 if (!silc_cipher_is_supported(cipher->name)) {
1434 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1435 silc_server_stop(server);
1440 /* Load (try at least) the crypto SIM module */
1441 char buf[1023], *alg_name;
1442 SilcCipherObject cipher_obj;
1445 memset(&cipher_obj, 0, sizeof(cipher_obj));
1446 cipher_obj.name = cipher->name;
1447 cipher_obj.block_len = cipher->block_length;
1448 cipher_obj.key_len = cipher->key_length * 8;
1450 /* build the libname */
1451 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1453 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1455 alg_name = strdup(cipher->name);
1456 if (strchr(alg_name, '-'))
1457 *strchr(alg_name, '-') = '\0';
1459 if (silc_sim_load(sim)) {
1460 cipher_obj.set_key =
1461 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1462 SILC_CIPHER_SIM_SET_KEY));
1463 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1464 cipher_obj.set_key_with_string =
1465 silc_sim_getsym(sim,
1466 silc_sim_symname(alg_name,
1467 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1468 SILC_LOG_DEBUG(("set_key_with_string=%p",
1469 cipher_obj.set_key_with_string));
1470 cipher_obj.encrypt =
1471 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1472 SILC_CIPHER_SIM_ENCRYPT_CBC));
1473 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1474 cipher_obj.decrypt =
1475 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1476 SILC_CIPHER_SIM_DECRYPT_CBC));
1477 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1478 cipher_obj.context_len =
1479 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1480 SILC_CIPHER_SIM_CONTEXT_LEN));
1481 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1483 /* Put the SIM to the list of all SIM's in server */
1484 silc_dlist_add(server->sim, sim);
1486 silc_free(alg_name);
1488 SILC_LOG_ERROR(("Error configuring ciphers"));
1489 silc_server_stop(server);
1493 /* Register the cipher */
1494 silc_cipher_register(&cipher_obj);
1496 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1497 "can't load modules!"));
1498 silc_server_stop(server);
1502 cipher = cipher->next;
1508 /* Registers configured hash functions. These can then be allocated by the
1509 server when needed. */
1511 bool silc_server_config_register_hashfuncs(SilcServer server)
1513 SilcServerConfig config = server->config;
1514 SilcServerConfigHash *hash = config->hash;
1515 char *module_path = config->module_path;
1517 SILC_LOG_DEBUG(("Registering configured hash functions"));
1519 if (!hash) /* any hash func in the config file? */
1523 /* if there isn't a module_path OR there isn't a module sim name try to
1524 * use buil-in functions */
1525 if (!module_path || !hash->module) {
1527 for (i = 0; silc_default_hash[i].name; i++)
1528 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1529 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1532 if (!silc_hash_is_supported(hash->name)) {
1533 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1534 silc_server_stop(server);
1539 /* Load (try at least) the hash SIM module */
1540 SilcHashObject hash_obj;
1543 memset(&hash_obj, 0, sizeof(hash_obj));
1544 hash_obj.name = hash->name;
1545 hash_obj.block_len = hash->block_length;
1546 hash_obj.hash_len = hash->digest_length;
1548 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1550 if ((silc_sim_load(sim))) {
1552 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1553 SILC_HASH_SIM_INIT));
1554 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1556 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1557 SILC_HASH_SIM_UPDATE));
1558 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1560 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1561 SILC_HASH_SIM_FINAL));
1562 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1563 hash_obj.context_len =
1564 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1565 SILC_HASH_SIM_CONTEXT_LEN));
1566 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1568 /* Put the SIM to the table of all SIM's in server */
1569 silc_dlist_add(server->sim, sim);
1571 SILC_LOG_ERROR(("Error configuring hash functions"));
1572 silc_server_stop(server);
1576 /* Register the hash function */
1577 silc_hash_register(&hash_obj);
1579 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1580 "can't load modules!"));
1581 silc_server_stop(server);
1591 /* Registers configure HMACs. These can then be allocated by the server
1594 bool silc_server_config_register_hmacs(SilcServer server)
1596 SilcServerConfig config = server->config;
1597 SilcServerConfigHmac *hmac = config->hmac;
1599 SILC_LOG_DEBUG(("Registering configured HMACs"));
1605 SilcHmacObject hmac_obj;
1606 if (!silc_hash_is_supported(hmac->hash)) {
1607 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1608 silc_server_stop(server);
1612 /* Register the HMAC */
1613 memset(&hmac_obj, 0, sizeof(hmac_obj));
1614 hmac_obj.name = hmac->name;
1615 hmac_obj.len = hmac->mac_length;
1616 silc_hmac_register(&hmac_obj);
1624 /* Registers configured PKCS's. */
1626 bool silc_server_config_register_pkcs(SilcServer server)
1628 SilcServerConfig config = server->config;
1629 SilcServerConfigPkcs *pkcs = config->pkcs;
1631 SILC_LOG_DEBUG(("Registering configured PKCS"));
1638 for (i = 0; silc_default_pkcs[i].name; i++)
1639 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1640 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1643 if (!silc_pkcs_is_supported(pkcs->name)) {
1644 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1645 silc_server_stop(server);
1654 /* Sets log files where log messages are saved by the server logger. */
1656 void silc_server_config_setlogfiles(SilcServer server)
1658 SilcServerConfig config = server->config;
1659 SilcServerConfigLogging *this;
1661 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1663 silc_log_quick = config->logging_quick;
1664 silc_log_flushdelay = (config->logging_flushdelay ?
1665 config->logging_flushdelay :
1666 SILC_SERVER_LOG_FLUSH_DELAY);
1668 if ((this = config->logging_fatals))
1669 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1671 if ((this = config->logging_errors))
1672 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1674 if ((this = config->logging_warnings))
1675 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1677 if ((this = config->logging_info))
1678 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1682 /* Returns client authentication information from configuration file by host
1685 SilcServerConfigClient *
1686 silc_server_config_find_client(SilcServer server, char *host)
1688 SilcServerConfig config = server->config;
1689 SilcServerConfigClient *client;
1691 if (!config || !host)
1694 for (client = config->clients; client; client = client->next) {
1695 if (client->host && !silc_string_compare(client->host, host))
1700 /* if none matched, then client is already NULL */
1704 /* Returns admin connection configuration by host, username and/or
1707 SilcServerConfigAdmin *
1708 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1711 SilcServerConfig config = server->config;
1712 SilcServerConfigAdmin *admin;
1714 /* make sure we have a value for the matching parameters */
1722 for (admin = config->admins; admin; admin = admin->next) {
1723 if (admin->host && !silc_string_compare(admin->host, host))
1725 if (admin->user && !silc_string_compare(admin->user, user))
1727 if (admin->nick && !silc_string_compare(admin->nick, nick))
1729 /* no checks failed -> this entry matches */
1733 /* if none matched, then admin is already NULL */
1737 /* Returns the denied connection configuration entry by host. */
1739 SilcServerConfigDeny *
1740 silc_server_config_find_denied(SilcServer server, char *host)
1742 SilcServerConfig config = server->config;
1743 SilcServerConfigDeny *deny;
1745 /* make sure we have a value for the matching parameters */
1746 if (!config || !host)
1749 for (deny = config->denied; deny; deny = deny->next) {
1750 if (deny->host && !silc_string_compare(deny->host, host))
1755 /* if none matched, then deny is already NULL */
1759 /* Returns server connection info from server configuartion by host
1762 SilcServerConfigServer *
1763 silc_server_config_find_server_conn(SilcServer server, char *host)
1765 SilcServerConfig config = server->config;
1766 SilcServerConfigServer *serv = NULL;
1771 if (!config->servers)
1774 for (serv = config->servers; serv; serv = serv->next) {
1775 if (!silc_string_compare(serv->host, host))
1783 /* Returns router connection info from server configuration by
1784 host (name or ip). */
1786 SilcServerConfigRouter *
1787 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1789 SilcServerConfig config = server->config;
1790 SilcServerConfigRouter *serv = NULL;
1795 if (!config->routers)
1798 for (serv = config->routers; serv; serv = serv->next) {
1799 if (!silc_string_compare(serv->host, host))
1801 if (port && serv->port && serv->port != port)
1809 /* Returns TRUE if configuration for a router connection that we are
1810 initiating exists. */
1812 bool silc_server_config_is_primary_route(SilcServer server)
1814 SilcServerConfig config = server->config;
1815 SilcServerConfigRouter *serv = NULL;
1819 serv = config->routers;
1820 for (i = 0; serv; i++) {
1821 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1832 /* Returns our primary connection configuration or NULL if we do not
1833 have primary router configured. */
1835 SilcServerConfigRouter *
1836 silc_server_config_get_primary_router(SilcServer server)
1838 SilcServerConfig config = server->config;
1839 SilcServerConfigRouter *serv = NULL;
1842 serv = config->routers;
1843 for (i = 0; serv; i++) {
1844 if (serv->initiator == TRUE && serv->backup_router == FALSE)