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) :
970 tmp->backup_router = TRUE;
972 else if (!strcmp(name, "backupport")) {
973 int port = *(int *)val;
974 if ((port <= 0) || (port > 65535)) {
975 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
976 "Invalid port number!\n"));
977 got_errno = SILC_CONFIG_EPRINTLINE;
980 tmp->backup_replace_port = (SilcUInt16) port;
982 else if (!strcmp(name, "backuplocal")) {
983 tmp->backup_local = *(bool *)val;
986 return SILC_CONFIG_EINTERNAL;
988 return SILC_CONFIG_OK;
991 silc_free(tmp->host);
992 silc_free(tmp->backup_replace_ip);
993 CONFIG_FREE_AUTH(tmp);
999 /* known config options tables */
1000 static const SilcConfigTable table_general[] = {
1001 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1002 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1003 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1004 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1005 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1006 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1007 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1008 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1009 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1010 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1011 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1012 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1013 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1014 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1015 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1016 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1017 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1018 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1019 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1020 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1024 static const SilcConfigTable table_cipher[] = {
1025 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1026 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1027 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1028 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1032 static const SilcConfigTable table_hash[] = {
1033 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1034 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1035 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1036 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1040 static const SilcConfigTable table_hmac[] = {
1041 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1042 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1043 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1047 static const SilcConfigTable table_pkcs[] = {
1048 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1052 static const SilcConfigTable table_serverinfo_c[] = {
1053 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1054 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1058 static const SilcConfigTable table_serverinfo[] = {
1059 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1060 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1061 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1062 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1063 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1064 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1065 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1066 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1067 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1068 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1069 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1070 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1071 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1075 static const SilcConfigTable table_logging_c[] = {
1076 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1077 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1078 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1082 static const SilcConfigTable table_logging[] = {
1083 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1084 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1085 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1086 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1087 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1088 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1092 static const SilcConfigTable table_connparam[] = {
1093 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1094 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1095 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1096 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1097 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1098 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1099 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1100 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1101 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1102 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1103 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1104 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1105 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1106 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1110 static const SilcConfigTable table_client[] = {
1111 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1112 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1113 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1114 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1118 static const SilcConfigTable table_admin[] = {
1119 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1120 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1121 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1122 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1123 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1124 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1125 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1129 static const SilcConfigTable table_deny[] = {
1130 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1131 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1135 static const SilcConfigTable table_serverconn[] = {
1136 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1137 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1138 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1139 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1140 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1144 static const SilcConfigTable table_routerconn[] = {
1145 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1146 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1147 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1148 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1149 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1150 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1151 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1152 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1153 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1157 static const SilcConfigTable table_main[] = {
1158 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1159 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1160 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1161 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1162 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1163 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1164 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1165 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1166 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1167 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1168 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1169 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1170 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1174 /* Set default values to stuff that was not configured. */
1176 static void silc_server_config_set_defaults(SilcServerConfig config)
1178 my_set_param_defaults(&config->param, NULL);
1180 config->channel_rekey_secs = (config->channel_rekey_secs ?
1181 config->channel_rekey_secs :
1182 SILC_SERVER_CHANNEL_REKEY);
1183 config->key_exchange_timeout = (config->key_exchange_timeout ?
1184 config->key_exchange_timeout :
1185 SILC_SERVER_SKE_TIMEOUT);
1186 config->conn_auth_timeout = (config->conn_auth_timeout ?
1187 config->conn_auth_timeout :
1188 SILC_SERVER_CONNAUTH_TIMEOUT);
1191 /* Allocates a new configuration object, opens configuration file and
1192 parses it. The parsed data is returned to the newly allocated
1193 configuration object. The SilcServerConfig must be freed by calling
1194 the silc_server_config_destroy function. */
1196 SilcServerConfig silc_server_config_alloc(const char *filename)
1198 SilcServerConfig config_new;
1199 SilcConfigEntity ent;
1200 SilcConfigFile *file;
1202 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1204 /* alloc a config object */
1205 config_new = silc_calloc(1, sizeof(*config_new));
1206 config_new->refcount = 1;
1210 /* obtain a config file object */
1211 file = silc_config_open(filename);
1213 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1218 /* obtain a SilcConfig entity, we can use it to start the parsing */
1219 ent = silc_config_init(file);
1221 /* load the known configuration options, give our empty object as context */
1222 silc_config_register_table(ent, table_main, (void *) config_new);
1224 /* enter the main parsing loop. When this returns, we have the parsing
1225 * result and the object filled (or partially, in case of errors). */
1226 ret = silc_config_main(ent);
1227 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1228 silc_config_strerror(ret)));
1230 /* Check if the parser returned errors */
1232 /* handle this special error return which asks to quietly return */
1233 if (ret != SILC_CONFIG_ESILENT) {
1234 char *linebuf, *filename = silc_config_get_filename(file);
1235 SilcUInt32 line = silc_config_get_line(file);
1236 if (ret != SILC_CONFIG_EPRINTLINE)
1237 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1238 silc_config_strerror(ret)));
1239 linebuf = silc_config_read_line(file, line);
1240 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n\n", filename,
1244 silc_server_config_destroy(config_new);
1248 /* close (destroy) the file object */
1249 silc_config_close(file);
1251 /* If config_new is incomplete, abort the object and return NULL */
1252 if (!config_new->server_info) {
1253 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1254 "`server_info'\n"));
1255 silc_server_config_destroy(config_new);
1259 /* Set default to configuration parameters */
1260 silc_server_config_set_defaults(config_new);
1265 /* Increments the reference counter of a config object */
1267 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1272 ref->config = config;
1273 ref->ref_ptr = ref_ptr;
1274 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1275 config->refcount - 1, config->refcount));
1279 /* Decrements the reference counter of a config object. If the counter
1280 reaches 0, the config object is destroyed. */
1282 void silc_server_config_unref(SilcServerConfigRef *ref)
1285 silc_server_config_destroy(ref->config);
1288 /* Destroy a config object with all his children lists */
1290 void silc_server_config_destroy(SilcServerConfig config)
1295 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1296 config->refcount + 1, config->refcount));
1297 if (config->refcount > 0)
1300 SILC_LOG_DEBUG(("Freeing config context"));
1302 /* Destroy general config stuff */
1303 silc_free(config->module_path);
1304 silc_free(config->param.version_protocol);
1305 silc_free(config->param.version_software);
1306 silc_free(config->param.version_software_vendor);
1308 /* Destroy Logging channels */
1309 if (config->logging_info)
1310 silc_free(config->logging_info->file);
1311 if (config->logging_warnings)
1312 silc_free(config->logging_warnings->file);
1313 if (config->logging_errors)
1314 silc_free(config->logging_errors->file);
1315 if (config->logging_fatals)
1316 silc_free(config->logging_fatals->file);
1318 /* Destroy the ServerInfo struct */
1319 if (config->server_info) {
1320 register SilcServerConfigServerInfo *si = config->server_info;
1321 silc_free(si->server_name);
1323 silc_free(si->primary->server_ip);
1324 silc_free(si->primary);
1326 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1328 silc_free(di->server_ip);
1331 silc_free(si->server_type);
1332 silc_free(si->location);
1333 silc_free(si->admin);
1334 silc_free(si->email);
1335 silc_free(si->user);
1336 silc_free(si->group);
1337 silc_free(si->motd_file);
1338 silc_free(si->pid_file);
1339 silc_pkcs_public_key_free(si->public_key);
1340 silc_pkcs_private_key_free(si->private_key);
1343 /* Now let's destroy the lists */
1345 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1347 silc_free(di->name);
1348 silc_free(di->module);
1351 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1352 silc_free(di->name);
1353 silc_free(di->module);
1356 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1357 silc_free(di->name);
1358 silc_free(di->hash);
1361 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1362 silc_free(di->name);
1365 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1366 config->conn_params)
1367 silc_free(di->name);
1368 silc_free(di->version_protocol);
1369 silc_free(di->version_software);
1370 silc_free(di->version_software_vendor);
1373 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1374 silc_free(di->host);
1375 CONFIG_FREE_AUTH(di);
1378 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1379 silc_free(di->host);
1380 silc_free(di->user);
1381 silc_free(di->nick);
1382 CONFIG_FREE_AUTH(di);
1385 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1386 silc_free(di->host);
1387 silc_free(di->reason);
1390 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1392 silc_free(di->host);
1393 CONFIG_FREE_AUTH(di);
1396 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1398 silc_free(di->host);
1399 silc_free(di->backup_replace_ip);
1400 CONFIG_FREE_AUTH(di);
1404 memset(config, 'F', sizeof(*config));
1408 /* Registers configured ciphers. These can then be allocated by the
1409 server when needed. */
1411 bool silc_server_config_register_ciphers(SilcServer server)
1413 SilcServerConfig config = server->config;
1414 SilcServerConfigCipher *cipher = config->cipher;
1415 char *module_path = config->module_path;
1417 SILC_LOG_DEBUG(("Registering configured ciphers"));
1419 if (!cipher) /* any cipher in the config file? */
1423 /* if there isn't a module_path OR there isn't a module sim name try to
1424 * use buil-in functions */
1425 if (!module_path || !cipher->module) {
1427 for (i = 0; silc_default_ciphers[i].name; i++)
1428 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1429 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1432 if (!silc_cipher_is_supported(cipher->name)) {
1433 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1434 silc_server_stop(server);
1439 /* Load (try at least) the crypto SIM module */
1440 char buf[1023], *alg_name;
1441 SilcCipherObject cipher_obj;
1444 memset(&cipher_obj, 0, sizeof(cipher_obj));
1445 cipher_obj.name = cipher->name;
1446 cipher_obj.block_len = cipher->block_length;
1447 cipher_obj.key_len = cipher->key_length * 8;
1449 /* build the libname */
1450 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1452 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1454 alg_name = strdup(cipher->name);
1455 if (strchr(alg_name, '-'))
1456 *strchr(alg_name, '-') = '\0';
1458 if (silc_sim_load(sim)) {
1459 cipher_obj.set_key =
1460 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1461 SILC_CIPHER_SIM_SET_KEY));
1462 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1463 cipher_obj.set_key_with_string =
1464 silc_sim_getsym(sim,
1465 silc_sim_symname(alg_name,
1466 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1467 SILC_LOG_DEBUG(("set_key_with_string=%p",
1468 cipher_obj.set_key_with_string));
1469 cipher_obj.encrypt =
1470 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1471 SILC_CIPHER_SIM_ENCRYPT_CBC));
1472 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1473 cipher_obj.decrypt =
1474 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1475 SILC_CIPHER_SIM_DECRYPT_CBC));
1476 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1477 cipher_obj.context_len =
1478 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1479 SILC_CIPHER_SIM_CONTEXT_LEN));
1480 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1482 /* Put the SIM to the list of all SIM's in server */
1483 silc_dlist_add(server->sim, sim);
1485 silc_free(alg_name);
1487 SILC_LOG_ERROR(("Error configuring ciphers"));
1488 silc_server_stop(server);
1492 /* Register the cipher */
1493 silc_cipher_register(&cipher_obj);
1495 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1496 "can't load modules!"));
1497 silc_server_stop(server);
1501 cipher = cipher->next;
1507 /* Registers configured hash functions. These can then be allocated by the
1508 server when needed. */
1510 bool silc_server_config_register_hashfuncs(SilcServer server)
1512 SilcServerConfig config = server->config;
1513 SilcServerConfigHash *hash = config->hash;
1514 char *module_path = config->module_path;
1516 SILC_LOG_DEBUG(("Registering configured hash functions"));
1518 if (!hash) /* any hash func in the config file? */
1522 /* if there isn't a module_path OR there isn't a module sim name try to
1523 * use buil-in functions */
1524 if (!module_path || !hash->module) {
1526 for (i = 0; silc_default_hash[i].name; i++)
1527 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1528 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1531 if (!silc_hash_is_supported(hash->name)) {
1532 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1533 silc_server_stop(server);
1538 /* Load (try at least) the hash SIM module */
1539 SilcHashObject hash_obj;
1542 memset(&hash_obj, 0, sizeof(hash_obj));
1543 hash_obj.name = hash->name;
1544 hash_obj.block_len = hash->block_length;
1545 hash_obj.hash_len = hash->digest_length;
1547 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1549 if ((silc_sim_load(sim))) {
1551 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1552 SILC_HASH_SIM_INIT));
1553 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1555 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1556 SILC_HASH_SIM_UPDATE));
1557 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1559 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1560 SILC_HASH_SIM_FINAL));
1561 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1562 hash_obj.context_len =
1563 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1564 SILC_HASH_SIM_CONTEXT_LEN));
1565 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1567 /* Put the SIM to the table of all SIM's in server */
1568 silc_dlist_add(server->sim, sim);
1570 SILC_LOG_ERROR(("Error configuring hash functions"));
1571 silc_server_stop(server);
1575 /* Register the hash function */
1576 silc_hash_register(&hash_obj);
1578 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1579 "can't load modules!"));
1580 silc_server_stop(server);
1590 /* Registers configure HMACs. These can then be allocated by the server
1593 bool silc_server_config_register_hmacs(SilcServer server)
1595 SilcServerConfig config = server->config;
1596 SilcServerConfigHmac *hmac = config->hmac;
1598 SILC_LOG_DEBUG(("Registering configured HMACs"));
1604 SilcHmacObject hmac_obj;
1605 if (!silc_hash_is_supported(hmac->hash)) {
1606 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1607 silc_server_stop(server);
1611 /* Register the HMAC */
1612 memset(&hmac_obj, 0, sizeof(hmac_obj));
1613 hmac_obj.name = hmac->name;
1614 hmac_obj.len = hmac->mac_length;
1615 silc_hmac_register(&hmac_obj);
1623 /* Registers configured PKCS's. */
1625 bool silc_server_config_register_pkcs(SilcServer server)
1627 SilcServerConfig config = server->config;
1628 SilcServerConfigPkcs *pkcs = config->pkcs;
1630 SILC_LOG_DEBUG(("Registering configured PKCS"));
1637 for (i = 0; silc_default_pkcs[i].name; i++)
1638 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1639 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1642 if (!silc_pkcs_is_supported(pkcs->name)) {
1643 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1644 silc_server_stop(server);
1653 /* Sets log files where log messages are saved by the server logger. */
1655 void silc_server_config_setlogfiles(SilcServer server)
1657 SilcServerConfig config = server->config;
1658 SilcServerConfigLogging *this;
1660 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1662 silc_log_quick = config->logging_quick;
1663 silc_log_flushdelay = (config->logging_flushdelay ?
1664 config->logging_flushdelay :
1665 SILC_SERVER_LOG_FLUSH_DELAY);
1667 if ((this = config->logging_fatals))
1668 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1670 if ((this = config->logging_errors))
1671 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1673 if ((this = config->logging_warnings))
1674 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1676 if ((this = config->logging_info))
1677 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1681 /* Returns client authentication information from configuration file by host
1684 SilcServerConfigClient *
1685 silc_server_config_find_client(SilcServer server, char *host)
1687 SilcServerConfig config = server->config;
1688 SilcServerConfigClient *client;
1690 if (!config || !host)
1693 for (client = config->clients; client; client = client->next) {
1694 if (client->host && !silc_string_compare(client->host, host))
1699 /* if none matched, then client is already NULL */
1703 /* Returns admin connection configuration by host, username and/or
1706 SilcServerConfigAdmin *
1707 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1710 SilcServerConfig config = server->config;
1711 SilcServerConfigAdmin *admin;
1713 /* make sure we have a value for the matching parameters */
1721 for (admin = config->admins; admin; admin = admin->next) {
1722 if (admin->host && !silc_string_compare(admin->host, host))
1724 if (admin->user && !silc_string_compare(admin->user, user))
1726 if (admin->nick && !silc_string_compare(admin->nick, nick))
1728 /* no checks failed -> this entry matches */
1732 /* if none matched, then admin is already NULL */
1736 /* Returns the denied connection configuration entry by host. */
1738 SilcServerConfigDeny *
1739 silc_server_config_find_denied(SilcServer server, char *host)
1741 SilcServerConfig config = server->config;
1742 SilcServerConfigDeny *deny;
1744 /* make sure we have a value for the matching parameters */
1745 if (!config || !host)
1748 for (deny = config->denied; deny; deny = deny->next) {
1749 if (deny->host && !silc_string_compare(deny->host, host))
1754 /* if none matched, then deny is already NULL */
1758 /* Returns server connection info from server configuartion by host
1761 SilcServerConfigServer *
1762 silc_server_config_find_server_conn(SilcServer server, char *host)
1764 SilcServerConfig config = server->config;
1765 SilcServerConfigServer *serv = NULL;
1770 if (!config->servers)
1773 for (serv = config->servers; serv; serv = serv->next) {
1774 if (!silc_string_compare(serv->host, host))
1782 /* Returns router connection info from server configuration by
1783 host (name or ip). */
1785 SilcServerConfigRouter *
1786 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1788 SilcServerConfig config = server->config;
1789 SilcServerConfigRouter *serv = NULL;
1794 if (!config->routers)
1797 for (serv = config->routers; serv; serv = serv->next) {
1798 if (!silc_string_compare(serv->host, host))
1800 if (port && serv->port && serv->port != port)
1808 /* Returns TRUE if configuration for a router connection that we are
1809 initiating exists. */
1811 bool silc_server_config_is_primary_route(SilcServer server)
1813 SilcServerConfig config = server->config;
1814 SilcServerConfigRouter *serv = NULL;
1818 serv = config->routers;
1819 for (i = 0; serv; i++) {
1820 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1831 /* Returns our primary connection configuration or NULL if we do not
1832 have primary router configured. */
1834 SilcServerConfigRouter *
1835 silc_server_config_get_primary_router(SilcServer server)
1837 SilcServerConfig config = server->config;
1838 SilcServerConfigRouter *serv = NULL;
1841 serv = config->routers;
1842 for (i = 0; serv; i++) {
1843 if (serv->initiator == TRUE && serv->backup_router == FALSE)